jazzy 0.14.4 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.github/workflows/Tests.yml +6 -5
 - data/.rubocop.yml +19 -0
 - data/CHANGELOG.md +56 -0
 - data/CONTRIBUTING.md +1 -1
 - data/Gemfile.lock +66 -49
 - data/README.md +115 -5
 - data/bin/sourcekitten +0 -0
 - data/jazzy.gemspec +1 -1
 - data/js/package-lock.json +6 -6
 - data/lib/jazzy/config.rb +156 -24
 - data/lib/jazzy/doc.rb +2 -2
 - data/lib/jazzy/doc_builder.rb +55 -29
 - data/lib/jazzy/doc_index.rb +185 -0
 - data/lib/jazzy/docset_builder/info_plist.mustache +1 -1
 - data/lib/jazzy/docset_builder.rb +44 -13
 - data/lib/jazzy/extensions/katex/css/katex.min.css +1 -1
 - data/lib/jazzy/extensions/katex/js/katex.min.js +1 -1
 - data/lib/jazzy/gem_version.rb +1 -1
 - data/lib/jazzy/grouper.rb +130 -0
 - data/lib/jazzy/podspec_documenter.rb +1 -1
 - data/lib/jazzy/source_declaration/type.rb +10 -2
 - data/lib/jazzy/source_declaration.rb +69 -8
 - data/lib/jazzy/source_document.rb +5 -1
 - data/lib/jazzy/source_module.rb +13 -11
 - data/lib/jazzy/sourcekitten.rb +232 -236
 - data/lib/jazzy/symbol_graph/ext_key.rb +37 -0
 - data/lib/jazzy/symbol_graph/ext_node.rb +23 -6
 - data/lib/jazzy/symbol_graph/graph.rb +31 -19
 - data/lib/jazzy/symbol_graph/relationship.rb +21 -3
 - data/lib/jazzy/symbol_graph/sym_node.rb +10 -22
 - data/lib/jazzy/symbol_graph/symbol.rb +28 -0
 - data/lib/jazzy/symbol_graph.rb +19 -16
 - data/lib/jazzy/themes/apple/assets/css/jazzy.css.scss +10 -7
 - data/lib/jazzy/themes/apple/assets/js/typeahead.jquery.js +3 -2
 - data/lib/jazzy/themes/apple/templates/doc.mustache +8 -1
 - data/lib/jazzy/themes/fullwidth/assets/css/jazzy.css.scss +5 -5
 - data/lib/jazzy/themes/fullwidth/assets/js/typeahead.jquery.js +3 -2
 - data/lib/jazzy/themes/fullwidth/templates/doc.mustache +8 -1
 - data/lib/jazzy/themes/jony/assets/css/jazzy.css.scss +6 -5
 - data/lib/jazzy/themes/jony/templates/doc.mustache +9 -2
 - data/spec/integration_spec.rb +8 -1
 - metadata +16 -7
 
    
        data/lib/jazzy/sourcekitten.rb
    CHANGED
    
    | 
         @@ -13,6 +13,8 @@ require 'jazzy/highlighter' 
     | 
|
| 
       13 
13 
     | 
    
         
             
            require 'jazzy/source_declaration'
         
     | 
| 
       14 
14 
     | 
    
         
             
            require 'jazzy/source_mark'
         
     | 
| 
       15 
15 
     | 
    
         
             
            require 'jazzy/stats'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'jazzy/grouper'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'jazzy/doc_index'
         
     | 
| 
       16 
18 
     | 
    
         | 
| 
       17 
19 
     | 
    
         
             
            ELIDED_AUTOLINK_TOKEN = '36f8f5912051ae747ef441d6511ca4cb'
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
         @@ -60,83 +62,9 @@ module Jazzy 
     | 
|
| 
       60 
62 
     | 
    
         
             
                  ).freeze
         
     | 
| 
       61 
63 
     | 
    
         
             
                end
         
     | 
| 
       62 
64 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
                # 
     | 
| 
       64 
     | 
    
         
            -
                 
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                  unlisted_prefix = Config.instance.custom_categories_unlisted_prefix
         
     | 
| 
       67 
     | 
    
         
            -
                  type_categories, uncategorized = group_type_categories(
         
     | 
| 
       68 
     | 
    
         
            -
                    docs, custom_categories.any? ? unlisted_prefix : ''
         
     | 
| 
       69 
     | 
    
         
            -
                  )
         
     | 
| 
       70 
     | 
    
         
            -
                  custom_categories + merge_categories(type_categories) + uncategorized
         
     | 
| 
       71 
     | 
    
         
            -
                end
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                def self.group_custom_categories(docs)
         
     | 
| 
       74 
     | 
    
         
            -
                  group = Config.instance.custom_categories.map do |category|
         
     | 
| 
       75 
     | 
    
         
            -
                    children = category['children'].flat_map do |name|
         
     | 
| 
       76 
     | 
    
         
            -
                      docs_with_name, docs = docs.partition { |doc| doc.name == name }
         
     | 
| 
       77 
     | 
    
         
            -
                      if docs_with_name.empty?
         
     | 
| 
       78 
     | 
    
         
            -
                        warn 'WARNING: No documented top-level declarations match ' \
         
     | 
| 
       79 
     | 
    
         
            -
                          "name \"#{name}\" specified in categories file"
         
     | 
| 
       80 
     | 
    
         
            -
                      end
         
     | 
| 
       81 
     | 
    
         
            -
                      docs_with_name
         
     | 
| 
       82 
     | 
    
         
            -
                    end
         
     | 
| 
       83 
     | 
    
         
            -
                    # Category config overrides alphabetization
         
     | 
| 
       84 
     | 
    
         
            -
                    children.each.with_index { |child, i| child.nav_order = i }
         
     | 
| 
       85 
     | 
    
         
            -
                    make_group(children, category['name'], '')
         
     | 
| 
       86 
     | 
    
         
            -
                  end
         
     | 
| 
       87 
     | 
    
         
            -
                  [group.compact, docs]
         
     | 
| 
       88 
     | 
    
         
            -
                end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                def self.group_type_categories(docs, type_category_prefix)
         
     | 
| 
       91 
     | 
    
         
            -
                  group = SourceDeclaration::Type.all.map do |type|
         
     | 
| 
       92 
     | 
    
         
            -
                    children, docs = docs.partition { |doc| doc.type == type }
         
     | 
| 
       93 
     | 
    
         
            -
                    make_group(
         
     | 
| 
       94 
     | 
    
         
            -
                      children,
         
     | 
| 
       95 
     | 
    
         
            -
                      type_category_prefix + type.plural_name,
         
     | 
| 
       96 
     | 
    
         
            -
                      "The following #{type.plural_name.downcase} are available globally.",
         
     | 
| 
       97 
     | 
    
         
            -
                      type_category_prefix + type.plural_url_name,
         
     | 
| 
       98 
     | 
    
         
            -
                    )
         
     | 
| 
       99 
     | 
    
         
            -
                  end
         
     | 
| 
       100 
     | 
    
         
            -
                  [group.compact, docs]
         
     | 
| 
       101 
     | 
    
         
            -
                end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                # Join categories with the same name (eg. ObjC and Swift classes)
         
     | 
| 
       104 
     | 
    
         
            -
                def self.merge_categories(categories)
         
     | 
| 
       105 
     | 
    
         
            -
                  merged = []
         
     | 
| 
       106 
     | 
    
         
            -
                  categories.each do |new_category|
         
     | 
| 
       107 
     | 
    
         
            -
                    if existing = merged.find { |c| c.name == new_category.name }
         
     | 
| 
       108 
     | 
    
         
            -
                      existing.children += new_category.children
         
     | 
| 
       109 
     | 
    
         
            -
                    else
         
     | 
| 
       110 
     | 
    
         
            -
                      merged.append(new_category)
         
     | 
| 
       111 
     | 
    
         
            -
                    end
         
     | 
| 
       112 
     | 
    
         
            -
                  end
         
     | 
| 
       113 
     | 
    
         
            -
                  merged
         
     | 
| 
       114 
     | 
    
         
            -
                end
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                def self.make_group(group, name, abstract, url_name = nil)
         
     | 
| 
       117 
     | 
    
         
            -
                  group.reject! { |doc| doc.name.empty? }
         
     | 
| 
       118 
     | 
    
         
            -
                  unless group.empty?
         
     | 
| 
       119 
     | 
    
         
            -
                    SourceDeclaration.new.tap do |sd|
         
     | 
| 
       120 
     | 
    
         
            -
                      sd.type     = SourceDeclaration::Type.overview
         
     | 
| 
       121 
     | 
    
         
            -
                      sd.name     = name
         
     | 
| 
       122 
     | 
    
         
            -
                      sd.url_name = url_name
         
     | 
| 
       123 
     | 
    
         
            -
                      sd.abstract = Markdown.render(abstract)
         
     | 
| 
       124 
     | 
    
         
            -
                      sd.children = group
         
     | 
| 
       125 
     | 
    
         
            -
                    end
         
     | 
| 
       126 
     | 
    
         
            -
                  end
         
     | 
| 
       127 
     | 
    
         
            -
                end
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                # Merge consecutive sections with the same mark into one section
         
     | 
| 
       130 
     | 
    
         
            -
                def self.merge_consecutive_marks(docs)
         
     | 
| 
       131 
     | 
    
         
            -
                  prev_mark = nil
         
     | 
| 
       132 
     | 
    
         
            -
                  docs.each do |doc|
         
     | 
| 
       133 
     | 
    
         
            -
                    if prev_mark&.can_merge?(doc.mark)
         
     | 
| 
       134 
     | 
    
         
            -
                      doc.mark = prev_mark
         
     | 
| 
       135 
     | 
    
         
            -
                    end
         
     | 
| 
       136 
     | 
    
         
            -
                    prev_mark = doc.mark
         
     | 
| 
       137 
     | 
    
         
            -
                    merge_consecutive_marks(doc.children)
         
     | 
| 
       138 
     | 
    
         
            -
                  end
         
     | 
| 
       139 
     | 
    
         
            -
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                # URL assignment
         
     | 
| 
      
 67 
     | 
    
         
            +
                #
         
     | 
| 
       140 
68 
     | 
    
         | 
| 
       141 
69 
     | 
    
         
             
                def self.sanitize_filename(doc)
         
     | 
| 
       142 
70 
     | 
    
         
             
                  unsafe_filename = doc.docs_filename
         
     | 
| 
         @@ -149,7 +77,7 @@ module Jazzy 
     | 
|
| 
       149 
77 
     | 
    
         
             
                end
         
     | 
| 
       150 
78 
     | 
    
         | 
| 
       151 
79 
     | 
    
         
             
                # rubocop:disable Metrics/MethodLength
         
     | 
| 
       152 
     | 
    
         
            -
                # Generate doc URL by prepending its parents URLs
         
     | 
| 
      
 80 
     | 
    
         
            +
                # Generate doc URL by prepending its parents' URLs
         
     | 
| 
       153 
81 
     | 
    
         
             
                # @return [Hash] input docs with URLs
         
     | 
| 
       154 
82 
     | 
    
         
             
                def self.make_doc_urls(docs)
         
     | 
| 
       155 
83 
     | 
    
         
             
                  docs.each do |doc|
         
     | 
| 
         @@ -189,18 +117,50 @@ module Jazzy 
     | 
|
| 
       189 
117 
     | 
    
         
             
                # Guides in the root for back-compatibility.
         
     | 
| 
       190 
118 
     | 
    
         
             
                # Declarations under outer namespace type (Structures, Classes, etc.)
         
     | 
| 
       191 
119 
     | 
    
         
             
                def self.subdir_for_doc(doc)
         
     | 
| 
       192 
     | 
    
         
            -
                   
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
                  top_level_decl = doc.namespace_path.first
         
     | 
| 
       195 
     | 
    
         
            -
                  if top_level_decl.type.name
         
     | 
| 
       196 
     | 
    
         
            -
                    [top_level_decl.type.plural_url_name] +
         
     | 
| 
       197 
     | 
    
         
            -
                      doc.namespace_ancestors.map(&:name)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  if Config.instance.multiple_modules?
         
     | 
| 
      
 121 
     | 
    
         
            +
                    subdir_for_doc_multi_module(doc)
         
     | 
| 
       198 
122 
     | 
    
         
             
                  else
         
     | 
| 
       199 
     | 
    
         
            -
                    #  
     | 
| 
       200 
     | 
    
         
            -
                     
     | 
| 
      
 123 
     | 
    
         
            +
                    # Back-compatibility layout version
         
     | 
| 
      
 124 
     | 
    
         
            +
                    subdir_for_doc_single_module(doc)
         
     | 
| 
       201 
125 
     | 
    
         
             
                  end
         
     | 
| 
       202 
126 
     | 
    
         
             
                end
         
     | 
| 
       203 
127 
     | 
    
         | 
| 
      
 128 
     | 
    
         
            +
                # Pre-multi-module site layout, does not allow for
         
     | 
| 
      
 129 
     | 
    
         
            +
                # types with the same name.
         
     | 
| 
      
 130 
     | 
    
         
            +
                def self.subdir_for_doc_single_module(doc)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  # Guides + Groups in the root
         
     | 
| 
      
 132 
     | 
    
         
            +
                  return [] if doc.type.markdown? || doc.type.overview?
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  [doc.namespace_path.first.type.plural_url_name] +
         
     | 
| 
      
 135 
     | 
    
         
            +
                    doc.namespace_ancestors.map(&:name)
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                # Multi-module site layout, separate each module that
         
     | 
| 
      
 139 
     | 
    
         
            +
                # is being documented.
         
     | 
| 
      
 140 
     | 
    
         
            +
                def self.subdir_for_doc_multi_module(doc)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  # Guides + Groups in the root
         
     | 
| 
      
 142 
     | 
    
         
            +
                  return [] if doc.type.markdown? || doc.type.overview?
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  root_decl = doc.namespace_path.first
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  # Extensions need an extra dir to allow for extending
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # ExternalModule1.TypeName and ExternalModule2.TypeName
         
     | 
| 
      
 148 
     | 
    
         
            +
                  namespace_subdir =
         
     | 
| 
      
 149 
     | 
    
         
            +
                    if root_decl.type.swift_extension?
         
     | 
| 
      
 150 
     | 
    
         
            +
                      ['Extensions', root_decl.module_name]
         
     | 
| 
      
 151 
     | 
    
         
            +
                    else
         
     | 
| 
      
 152 
     | 
    
         
            +
                      [doc.namespace_path.first.type.plural_url_name]
         
     | 
| 
      
 153 
     | 
    
         
            +
                    end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                  [root_decl.doc_module_name] +
         
     | 
| 
      
 156 
     | 
    
         
            +
                    namespace_subdir +
         
     | 
| 
      
 157 
     | 
    
         
            +
                    doc.namespace_ancestors.map(&:name)
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                #
         
     | 
| 
      
 161 
     | 
    
         
            +
                # CLI argument calculation
         
     | 
| 
      
 162 
     | 
    
         
            +
                #
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
       204 
164 
     | 
    
         
             
                # returns all subdirectories of specified path
         
     | 
| 
       205 
165 
     | 
    
         
             
                def self.rec_path(path)
         
     | 
| 
       206 
166 
     | 
    
         
             
                  path.children.collect do |child|
         
     | 
| 
         @@ -210,42 +170,42 @@ module Jazzy 
     | 
|
| 
       210 
170 
     | 
    
         
             
                  end.select { |x| x }.flatten(1)
         
     | 
| 
       211 
171 
     | 
    
         
             
                end
         
     | 
| 
       212 
172 
     | 
    
         | 
| 
       213 
     | 
    
         
            -
                def self.use_spm?( 
     | 
| 
       214 
     | 
    
         
            -
                   
     | 
| 
       215 
     | 
    
         
            -
                    (! 
     | 
| 
      
 173 
     | 
    
         
            +
                def self.use_spm?(module_config)
         
     | 
| 
      
 174 
     | 
    
         
            +
                  module_config.swift_build_tool == :spm ||
         
     | 
| 
      
 175 
     | 
    
         
            +
                    (!module_config.swift_build_tool_configured &&
         
     | 
| 
       216 
176 
     | 
    
         
             
                     Dir['*.xcodeproj', '*.xcworkspace'].empty? &&
         
     | 
| 
       217 
     | 
    
         
            -
                     ! 
     | 
| 
       218 
     | 
    
         
            -
                     ! 
     | 
| 
      
 177 
     | 
    
         
            +
                     !module_config.build_tool_arguments.include?('-project') &&
         
     | 
| 
      
 178 
     | 
    
         
            +
                     !module_config.build_tool_arguments.include?('-workspace'))
         
     | 
| 
       219 
179 
     | 
    
         
             
                end
         
     | 
| 
       220 
180 
     | 
    
         | 
| 
       221 
181 
     | 
    
         
             
                # Builds SourceKitten arguments based on Jazzy options
         
     | 
| 
       222 
     | 
    
         
            -
                def self.arguments_from_options( 
     | 
| 
      
 182 
     | 
    
         
            +
                def self.arguments_from_options(module_config)
         
     | 
| 
       223 
183 
     | 
    
         
             
                  arguments = ['doc']
         
     | 
| 
       224 
     | 
    
         
            -
                  if  
     | 
| 
       225 
     | 
    
         
            -
                    arguments += objc_arguments_from_options( 
     | 
| 
      
 184 
     | 
    
         
            +
                  if module_config.objc_mode
         
     | 
| 
      
 185 
     | 
    
         
            +
                    arguments += objc_arguments_from_options(module_config)
         
     | 
| 
       226 
186 
     | 
    
         
             
                  else
         
     | 
| 
       227 
     | 
    
         
            -
                    arguments += ['--spm'] if use_spm?( 
     | 
| 
       228 
     | 
    
         
            -
                    unless  
     | 
| 
       229 
     | 
    
         
            -
                      arguments += ['--module-name',  
     | 
| 
      
 187 
     | 
    
         
            +
                    arguments += ['--spm'] if use_spm?(module_config)
         
     | 
| 
      
 188 
     | 
    
         
            +
                    unless module_config.module_name.empty?
         
     | 
| 
      
 189 
     | 
    
         
            +
                      arguments += ['--module-name', module_config.module_name]
         
     | 
| 
       230 
190 
     | 
    
         
             
                    end
         
     | 
| 
       231 
191 
     | 
    
         
             
                    arguments += ['--']
         
     | 
| 
       232 
192 
     | 
    
         
             
                  end
         
     | 
| 
       233 
193 
     | 
    
         | 
| 
       234 
     | 
    
         
            -
                  arguments +  
     | 
| 
      
 194 
     | 
    
         
            +
                  arguments + module_config.build_tool_arguments
         
     | 
| 
       235 
195 
     | 
    
         
             
                end
         
     | 
| 
       236 
196 
     | 
    
         | 
| 
       237 
     | 
    
         
            -
                def self.objc_arguments_from_options( 
     | 
| 
      
 197 
     | 
    
         
            +
                def self.objc_arguments_from_options(module_config)
         
     | 
| 
       238 
198 
     | 
    
         
             
                  arguments = []
         
     | 
| 
       239 
     | 
    
         
            -
                  if  
     | 
| 
       240 
     | 
    
         
            -
                    arguments += ['--objc',  
     | 
| 
      
 199 
     | 
    
         
            +
                  if module_config.build_tool_arguments.empty?
         
     | 
| 
      
 200 
     | 
    
         
            +
                    arguments += ['--objc', module_config.umbrella_header.to_s, '--', '-x',
         
     | 
| 
       241 
201 
     | 
    
         
             
                                  'objective-c', '-isysroot',
         
     | 
| 
       242 
     | 
    
         
            -
                                  `xcrun --show-sdk-path --sdk #{ 
     | 
| 
       243 
     | 
    
         
            -
                                  '-I',  
     | 
| 
      
 202 
     | 
    
         
            +
                                  `xcrun --show-sdk-path --sdk #{module_config.sdk}`.chomp,
         
     | 
| 
      
 203 
     | 
    
         
            +
                                  '-I', module_config.framework_root.to_s,
         
     | 
| 
       244 
204 
     | 
    
         
             
                                  '-fmodules']
         
     | 
| 
       245 
205 
     | 
    
         
             
                  end
         
     | 
| 
       246 
206 
     | 
    
         
             
                  # add additional -I arguments for each subdirectory of framework_root
         
     | 
| 
       247 
     | 
    
         
            -
                  unless  
     | 
| 
       248 
     | 
    
         
            -
                    rec_path(Pathname.new( 
     | 
| 
      
 207 
     | 
    
         
            +
                  unless module_config.framework_root.nil?
         
     | 
| 
      
 208 
     | 
    
         
            +
                    rec_path(Pathname.new(module_config.framework_root.to_s)).collect do |child|
         
     | 
| 
       249 
209 
     | 
    
         
             
                      if child.directory?
         
     | 
| 
       250 
210 
     | 
    
         
             
                        arguments += ['-I', child.to_s]
         
     | 
| 
       251 
211 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -270,6 +230,10 @@ module Jazzy 
     | 
|
| 
       270 
230 
     | 
    
         
             
                  output
         
     | 
| 
       271 
231 
     | 
    
         
             
                end
         
     | 
| 
       272 
232 
     | 
    
         | 
| 
      
 233 
     | 
    
         
            +
                #
         
     | 
| 
      
 234 
     | 
    
         
            +
                # SourceDeclaration generation
         
     | 
| 
      
 235 
     | 
    
         
            +
                #
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
       273 
237 
     | 
    
         
             
                def self.make_default_doc_info(declaration)
         
     | 
| 
       274 
238 
     | 
    
         
             
                  # @todo: Fix these
         
     | 
| 
       275 
239 
     | 
    
         
             
                  declaration.abstract = ''
         
     | 
| 
         @@ -352,18 +316,10 @@ module Jazzy 
     | 
|
| 
       352 
316 
     | 
    
         
             
                    end
         
     | 
| 
       353 
317 
     | 
    
         
             
                end
         
     | 
| 
       354 
318 
     | 
    
         | 
| 
       355 
     | 
    
         
            -
                # Call things undocumented if they were compiled properly
         
     | 
| 
       356 
     | 
    
         
            -
                # and came from our module.
         
     | 
| 
       357 
     | 
    
         
            -
                def self.should_mark_undocumented(declaration)
         
     | 
| 
       358 
     | 
    
         
            -
                  declaration.usr &&
         
     | 
| 
       359 
     | 
    
         
            -
                    (declaration.modulename.nil? ||
         
     | 
| 
       360 
     | 
    
         
            -
                     declaration.modulename == Config.instance.module_name)
         
     | 
| 
       361 
     | 
    
         
            -
                end
         
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
       363 
319 
     | 
    
         
             
                def self.process_undocumented_token(doc, declaration)
         
     | 
| 
       364 
320 
     | 
    
         
             
                  make_default_doc_info(declaration)
         
     | 
| 
       365 
321 
     | 
    
         | 
| 
       366 
     | 
    
         
            -
                  if  
     | 
| 
      
 322 
     | 
    
         
            +
                  if declaration.mark_undocumented?
         
     | 
| 
       367 
323 
     | 
    
         
             
                    @stats.add_undocumented(declaration)
         
     | 
| 
       368 
324 
     | 
    
         
             
                    return nil if @skip_undocumented
         
     | 
| 
       369 
325 
     | 
    
         | 
| 
         @@ -621,7 +577,15 @@ module Jazzy 
     | 
|
| 
       621 
577 
     | 
    
         
             
                    declaration.file = Pathname(doc['key.filepath']) if doc['key.filepath']
         
     | 
| 
       622 
578 
     | 
    
         
             
                    declaration.usr = doc['key.usr']
         
     | 
| 
       623 
579 
     | 
    
         
             
                    declaration.type_usr = doc['key.typeusr']
         
     | 
| 
       624 
     | 
    
         
            -
                    declaration. 
     | 
| 
      
 580 
     | 
    
         
            +
                    declaration.module_name =
         
     | 
| 
      
 581 
     | 
    
         
            +
                      if declaration.swift?
         
     | 
| 
      
 582 
     | 
    
         
            +
                        # Filter out Apple sub-framework implementation names
         
     | 
| 
      
 583 
     | 
    
         
            +
                        doc['key.modulename']&.sub(/\..*$/, '')
         
     | 
| 
      
 584 
     | 
    
         
            +
                      else
         
     | 
| 
      
 585 
     | 
    
         
            +
                        # ObjC best effort, category original module is unavailable
         
     | 
| 
      
 586 
     | 
    
         
            +
                        @current_module_name
         
     | 
| 
      
 587 
     | 
    
         
            +
                      end
         
     | 
| 
      
 588 
     | 
    
         
            +
                    declaration.doc_module_name = @current_module_name
         
     | 
| 
       625 
589 
     | 
    
         
             
                    declaration.name = documented_name
         
     | 
| 
       626 
590 
     | 
    
         
             
                    declaration.mark = current_mark
         
     | 
| 
       627 
591 
     | 
    
         
             
                    declaration.access_control_level =
         
     | 
| 
         @@ -665,6 +629,10 @@ module Jazzy 
     | 
|
| 
       665 
629 
     | 
    
         
             
                  Regexp.last_match[1].gsub(/\s+/, ' ')
         
     | 
| 
       666 
630 
     | 
    
         
             
                end
         
     | 
| 
       667 
631 
     | 
    
         | 
| 
      
 632 
     | 
    
         
            +
                #
         
     | 
| 
      
 633 
     | 
    
         
            +
                # SourceDeclaration generation - extension management
         
     | 
| 
      
 634 
     | 
    
         
            +
                #
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
       668 
636 
     | 
    
         
             
                # Expands extensions of nested types declared at the top level into
         
     | 
| 
       669 
637 
     | 
    
         
             
                # a tree so they can be deduplicated properly
         
     | 
| 
       670 
638 
     | 
    
         
             
                def self.expand_extensions(decls)
         
     | 
| 
         @@ -689,7 +657,8 @@ module Jazzy 
     | 
|
| 
       689 
657 
     | 
    
         
             
                  SourceDeclaration.new.tap do |decl|
         
     | 
| 
       690 
658 
     | 
    
         
             
                    make_default_doc_info(decl)
         
     | 
| 
       691 
659 
     | 
    
         
             
                    decl.name = name
         
     | 
| 
       692 
     | 
    
         
            -
                    decl. 
     | 
| 
      
 660 
     | 
    
         
            +
                    decl.module_name = extension.module_name
         
     | 
| 
      
 661 
     | 
    
         
            +
                    decl.doc_module_name = extension.doc_module_name
         
     | 
| 
       693 
662 
     | 
    
         
             
                    decl.type = extension.type
         
     | 
| 
       694 
663 
     | 
    
         
             
                    decl.mark = extension.mark
         
     | 
| 
       695 
664 
     | 
    
         
             
                    decl.usr = candidates.first.usr unless candidates.empty?
         
     | 
| 
         @@ -720,9 +689,10 @@ module Jazzy 
     | 
|
| 
       720 
689 
     | 
    
         | 
| 
       721 
690 
     | 
    
         
             
                # Returns true if an Objective-C declaration is mergeable.
         
     | 
| 
       722 
691 
     | 
    
         
             
                def self.mergeable_objc?(decl, root_decls)
         
     | 
| 
       723 
     | 
    
         
            -
                  decl.type.objc_class?  
     | 
| 
       724 
     | 
    
         
            -
                     
     | 
| 
       725 
     | 
    
         
            -
             
     | 
| 
      
 692 
     | 
    
         
            +
                  decl.type.objc_class? ||
         
     | 
| 
      
 693 
     | 
    
         
            +
                    (decl.type.objc_category? &&
         
     | 
| 
      
 694 
     | 
    
         
            +
                      (category_classname = decl.objc_category_name[0]) &&
         
     | 
| 
      
 695 
     | 
    
         
            +
                      root_decls.any? { |d| d.name == category_classname })
         
     | 
| 
       726 
696 
     | 
    
         
             
                end
         
     | 
| 
       727 
697 
     | 
    
         | 
| 
       728 
698 
     | 
    
         
             
                # Returns if a Swift declaration is mergeable.
         
     | 
| 
         @@ -733,22 +703,45 @@ module Jazzy 
     | 
|
| 
       733 
703 
     | 
    
         
             
                    decl.type.swift_typealias?
         
     | 
| 
       734 
704 
     | 
    
         
             
                end
         
     | 
| 
       735 
705 
     | 
    
         | 
| 
      
 706 
     | 
    
         
            +
                # Normally merge all extensions into their types and each other.
         
     | 
| 
      
 707 
     | 
    
         
            +
                #
         
     | 
| 
      
 708 
     | 
    
         
            +
                # :none means only merge within a module -- so two extensions to
         
     | 
| 
      
 709 
     | 
    
         
            +
                #     some type get merged, but an extension to a type from
         
     | 
| 
      
 710 
     | 
    
         
            +
                #     another documented module does not get merged into that type
         
     | 
| 
      
 711 
     | 
    
         
            +
                # :extensions means extensions of documented modules get merged,
         
     | 
| 
      
 712 
     | 
    
         
            +
                #     but if we're documenting ModA and ModB, and they both provide
         
     | 
| 
      
 713 
     | 
    
         
            +
                #     extensions to Swift.String, then those two extensions still
         
     | 
| 
      
 714 
     | 
    
         
            +
                #     appear separately.
         
     | 
| 
      
 715 
     | 
    
         
            +
                #
         
     | 
| 
      
 716 
     | 
    
         
            +
                # (The USR part of the dedup key means ModA.Foo and ModB.Foo do not
         
     | 
| 
      
 717 
     | 
    
         
            +
                # get merged.)
         
     | 
| 
      
 718 
     | 
    
         
            +
                def self.module_deduplication_key(decl)
         
     | 
| 
      
 719 
     | 
    
         
            +
                  if (Config.instance.merge_modules == :none) ||
         
     | 
| 
      
 720 
     | 
    
         
            +
                     (Config.instance.merge_modules == :extensions &&
         
     | 
| 
      
 721 
     | 
    
         
            +
                      decl.extension_of_external_type?)
         
     | 
| 
      
 722 
     | 
    
         
            +
                    decl.doc_module_name
         
     | 
| 
      
 723 
     | 
    
         
            +
                  else
         
     | 
| 
      
 724 
     | 
    
         
            +
                    ''
         
     | 
| 
      
 725 
     | 
    
         
            +
                  end
         
     | 
| 
      
 726 
     | 
    
         
            +
                end
         
     | 
| 
      
 727 
     | 
    
         
            +
             
     | 
| 
       736 
728 
     | 
    
         
             
                # Two declarations get merged if they have the same deduplication key.
         
     | 
| 
       737 
729 
     | 
    
         
             
                def self.deduplication_key(decl, root_decls)
         
     | 
| 
      
 730 
     | 
    
         
            +
                  mod_key = module_deduplication_key(decl)
         
     | 
| 
       738 
731 
     | 
    
         
             
                  # Swift extension of objc class
         
     | 
| 
       739 
732 
     | 
    
         
             
                  if decl.swift_objc_extension?
         
     | 
| 
       740 
     | 
    
         
            -
                    [decl.swift_extension_objc_name, :objc_class_and_categories]
         
     | 
| 
      
 733 
     | 
    
         
            +
                    [decl.swift_extension_objc_name, :objc_class_and_categories, mod_key]
         
     | 
| 
       741 
734 
     | 
    
         
             
                  # Swift type or Swift extension of Swift type
         
     | 
| 
       742 
735 
     | 
    
         
             
                  elsif mergeable_swift?(decl)
         
     | 
| 
       743 
     | 
    
         
            -
                    [decl.usr, decl.name]
         
     | 
| 
      
 736 
     | 
    
         
            +
                    [decl.usr, decl.name, mod_key]
         
     | 
| 
       744 
737 
     | 
    
         
             
                  # Objc categories and classes
         
     | 
| 
       745 
738 
     | 
    
         
             
                  elsif mergeable_objc?(decl, root_decls)
         
     | 
| 
       746 
739 
     | 
    
         
             
                    # Using the ObjC name to match swift_objc_extension.
         
     | 
| 
       747 
740 
     | 
    
         
             
                    name, _ = decl.objc_category_name || decl.objc_name
         
     | 
| 
       748 
     | 
    
         
            -
                    [name, :objc_class_and_categories]
         
     | 
| 
      
 741 
     | 
    
         
            +
                    [name, :objc_class_and_categories, mod_key]
         
     | 
| 
       749 
742 
     | 
    
         
             
                  # Non-mergable declarations (funcs, typedefs etc...)
         
     | 
| 
       750 
743 
     | 
    
         
             
                  else
         
     | 
| 
       751 
     | 
    
         
            -
                    [decl.usr, decl.name, decl.type.kind]
         
     | 
| 
      
 744 
     | 
    
         
            +
                    [decl.usr, decl.name, decl.type.kind, '']
         
     | 
| 
       752 
745 
     | 
    
         
             
                  end
         
     | 
| 
       753 
746 
     | 
    
         
             
                end
         
     | 
| 
       754 
747 
     | 
    
         | 
| 
         @@ -904,81 +897,47 @@ module Jazzy 
     | 
|
| 
       904 
897 
     | 
    
         
             
                # declaration: public protocol conformances and, for top-level extensions,
         
     | 
| 
       905 
898 
     | 
    
         
             
                # further conditional extensions of the same type.
         
     | 
| 
       906 
899 
     | 
    
         
             
                def self.merge_code_declaration(decls)
         
     | 
| 
       907 
     | 
    
         
            -
                  first = decls.first
         
     | 
| 
       908 
     | 
    
         
            -
             
     | 
| 
       909 
900 
     | 
    
         
             
                  declarations = decls[1..].select do |decl|
         
     | 
| 
       910 
901 
     | 
    
         
             
                    decl.type.swift_extension? &&
         
     | 
| 
       911 
902 
     | 
    
         
             
                      (decl.other_inherited_types?(@inaccessible_protocols) ||
         
     | 
| 
       912 
     | 
    
         
            -
                        (first.type.swift_extension? && decl.constrained_extension?))
         
     | 
| 
       913 
     | 
    
         
            -
                  end. 
     | 
| 
       914 
     | 
    
         
            -
             
     | 
| 
       915 
     | 
    
         
            -
                   
     | 
| 
       916 
     | 
    
         
            -
             
     | 
| 
       917 
     | 
    
         
            -
             
     | 
| 
       918 
     | 
    
         
            -
             
     | 
| 
       919 
     | 
    
         
            -
             
     | 
| 
       920 
     | 
    
         
            -
             
     | 
| 
       921 
     | 
    
         
            -
                def self.filter_files(json)
         
     | 
| 
       922 
     | 
    
         
            -
                  json = filter_included_files(json) if Config.instance.included_files.any?
         
     | 
| 
       923 
     | 
    
         
            -
                  json = filter_excluded_files(json) if Config.instance.excluded_files.any?
         
     | 
| 
       924 
     | 
    
         
            -
                  json.map do |doc|
         
     | 
| 
       925 
     | 
    
         
            -
                    key = doc.keys.first
         
     | 
| 
       926 
     | 
    
         
            -
                    doc[key]
         
     | 
| 
       927 
     | 
    
         
            -
                  end.compact
         
     | 
| 
       928 
     | 
    
         
            -
                end
         
     | 
| 
       929 
     | 
    
         
            -
             
     | 
| 
       930 
     | 
    
         
            -
                # Filter based on the "included" flag.
         
     | 
| 
       931 
     | 
    
         
            -
                def self.filter_included_files(json)
         
     | 
| 
       932 
     | 
    
         
            -
                  included_files = Config.instance.included_files
         
     | 
| 
       933 
     | 
    
         
            -
                  json.map do |doc|
         
     | 
| 
       934 
     | 
    
         
            -
                    key = doc.keys.first
         
     | 
| 
       935 
     | 
    
         
            -
                    doc if included_files.detect do |include|
         
     | 
| 
       936 
     | 
    
         
            -
                      File.fnmatch?(include, key)
         
     | 
| 
      
 903 
     | 
    
         
            +
                        (decls.first.type.swift_extension? && decl.constrained_extension?))
         
     | 
| 
      
 904 
     | 
    
         
            +
                  end.prepend(decls.first)
         
     | 
| 
      
 905 
     | 
    
         
            +
             
     | 
| 
      
 906 
     | 
    
         
            +
                  html_declaration = ''
         
     | 
| 
      
 907 
     | 
    
         
            +
                  until declarations.empty?
         
     | 
| 
      
 908 
     | 
    
         
            +
                    module_decls, declarations = next_doc_module_group(declarations)
         
     | 
| 
      
 909 
     | 
    
         
            +
                    first = module_decls.first
         
     | 
| 
      
 910 
     | 
    
         
            +
                    if need_doc_module_note?(first, html_declaration)
         
     | 
| 
      
 911 
     | 
    
         
            +
                      html_declaration += "<span class='declaration-note'>From #{first.doc_module_name}:</span>"
         
     | 
| 
       937 
912 
     | 
    
         
             
                    end
         
     | 
| 
       938 
     | 
    
         
            -
             
     | 
| 
       939 
     | 
    
         
            -
             
     | 
| 
      
 913 
     | 
    
         
            +
                    html_declaration += module_decls.map(&:declaration).uniq.join
         
     | 
| 
      
 914 
     | 
    
         
            +
                  end
         
     | 
| 
       940 
915 
     | 
    
         | 
| 
       941 
     | 
    
         
            -
             
     | 
| 
       942 
     | 
    
         
            -
             
     | 
| 
       943 
     | 
    
         
            -
                  excluded_files = Config.instance.excluded_files
         
     | 
| 
       944 
     | 
    
         
            -
                  json.map do |doc|
         
     | 
| 
       945 
     | 
    
         
            -
                    key = doc.keys.first
         
     | 
| 
       946 
     | 
    
         
            -
                    doc unless excluded_files.detect do |exclude|
         
     | 
| 
       947 
     | 
    
         
            -
                      File.fnmatch?(exclude, key)
         
     | 
| 
       948 
     | 
    
         
            -
                    end
         
     | 
| 
       949 
     | 
    
         
            -
                  end.compact
         
     | 
| 
      
 916 
     | 
    
         
            +
                  # Must preserve `nil` for edge cases
         
     | 
| 
      
 917 
     | 
    
         
            +
                  decls.first.declaration = html_declaration unless html_declaration.empty?
         
     | 
| 
       950 
918 
     | 
    
         
             
                end
         
     | 
| 
       951 
919 
     | 
    
         | 
| 
       952 
     | 
    
         
            -
                 
     | 
| 
       953 
     | 
    
         
            -
             
     | 
| 
       954 
     | 
    
         
            -
             
     | 
| 
       955 
     | 
    
         
            -
             
     | 
| 
       956 
     | 
    
         
            -
                    .gsub('\.\.\.', '[^)]*')
         
     | 
| 
       957 
     | 
    
         
            -
                    .gsub(/<.*>/, '')
         
     | 
| 
       958 
     | 
    
         
            -
             
     | 
| 
       959 
     | 
    
         
            -
                  whole_name_pat = /\A#{wildcard_expansion}\Z/
         
     | 
| 
       960 
     | 
    
         
            -
                  docs.find do |doc|
         
     | 
| 
       961 
     | 
    
         
            -
                    whole_name_pat =~ doc.name
         
     | 
| 
      
 920 
     | 
    
         
            +
                # Grab all the extensions from the same doc module
         
     | 
| 
      
 921 
     | 
    
         
            +
                def self.next_doc_module_group(decls)
         
     | 
| 
      
 922 
     | 
    
         
            +
                  decls.partition do |decl|
         
     | 
| 
      
 923 
     | 
    
         
            +
                    decl.doc_module_name == decls.first.doc_module_name
         
     | 
| 
       962 
924 
     | 
    
         
             
                  end
         
     | 
| 
       963 
925 
     | 
    
         
             
                end
         
     | 
| 
       964 
926 
     | 
    
         | 
| 
       965 
     | 
    
         
            -
                #  
     | 
| 
       966 
     | 
    
         
            -
                 
     | 
| 
       967 
     | 
    
         
            -
             
     | 
| 
       968 
     | 
    
         
            -
             
     | 
| 
       969 
     | 
    
         
            -
             
     | 
| 
       970 
     | 
    
         
            -
                     
     | 
| 
       971 
     | 
    
         
            -
             
     | 
| 
       972 
     | 
    
         
            -
             
     | 
| 
      
 927 
     | 
    
         
            +
                # Does this extension/type need a note explaining which doc module it is from?
         
     | 
| 
      
 928 
     | 
    
         
            +
                # Only for extensions, if there actually are multiple modules.
         
     | 
| 
      
 929 
     | 
    
         
            +
                # Last condition avoids it for simple 'extension Array'.
         
     | 
| 
      
 930 
     | 
    
         
            +
                def self.need_doc_module_note?(decl, html_declaration)
         
     | 
| 
      
 931 
     | 
    
         
            +
                  Config.instance.multiple_modules? &&
         
     | 
| 
      
 932 
     | 
    
         
            +
                    decl.type.swift_extension? &&
         
     | 
| 
      
 933 
     | 
    
         
            +
                    !(html_declaration.empty? &&
         
     | 
| 
      
 934 
     | 
    
         
            +
                      !decl.constrained_extension? &&
         
     | 
| 
      
 935 
     | 
    
         
            +
                      !decl.inherited_types?)
         
     | 
| 
       973 
936 
     | 
    
         
             
                end
         
     | 
| 
       974 
937 
     | 
    
         | 
| 
       975 
     | 
    
         
            -
                 
     | 
| 
       976 
     | 
    
         
            -
             
     | 
| 
       977 
     | 
    
         
            -
             
     | 
| 
       978 
     | 
    
         
            -
                    doc = name_match(next_part, doc.children)
         
     | 
| 
       979 
     | 
    
         
            -
                  end
         
     | 
| 
       980 
     | 
    
         
            -
                  doc
         
     | 
| 
       981 
     | 
    
         
            -
                end
         
     | 
| 
      
 938 
     | 
    
         
            +
                #
         
     | 
| 
      
 939 
     | 
    
         
            +
                # Autolinking
         
     | 
| 
      
 940 
     | 
    
         
            +
                #
         
     | 
| 
       982 
941 
     | 
    
         | 
| 
       983 
942 
     | 
    
         
             
                # Links recognized top-level declarations within
         
     | 
| 
       984 
943 
     | 
    
         
             
                # - inlined code within docs
         
     | 
| 
         @@ -987,85 +946,97 @@ module Jazzy 
     | 
|
| 
       987 
946 
     | 
    
         
             
                # The `after_highlight` flag is used to differentiate between the two modes.
         
     | 
| 
       988 
947 
     | 
    
         
             
                #
         
     | 
| 
       989 
948 
     | 
    
         
             
                # DocC link format - follow Xcode and don't display slash-separated parts.
         
     | 
| 
       990 
     | 
    
         
            -
                 
     | 
| 
       991 
     | 
    
         
            -
                def self.autolink_text(text, doc, root_decls, after_highlight: false)
         
     | 
| 
      
 949 
     | 
    
         
            +
                def self.autolink_text(text, doc, after_highlight: false)
         
     | 
| 
       992 
950 
     | 
    
         
             
                  text.autolink_block(doc.url, '[^\s]+', after_highlight) do |raw_name|
         
     | 
| 
       993 
951 
     | 
    
         
             
                    sym_name =
         
     | 
| 
       994 
952 
     | 
    
         
             
                      (raw_name[/^<doc:(.*)>$/, 1] || raw_name).sub(/(?<!^)-.+$/, '')
         
     | 
| 
       995 
953 
     | 
    
         | 
| 
       996 
     | 
    
         
            -
                     
     | 
| 
       997 
     | 
    
         
            -
                      .sub(/^@/, '') # ignore for custom attribute ref
         
     | 
| 
       998 
     | 
    
         
            -
                      .split(%r{(?<!\.)[/.](?!\.)}) # dot or slash, but not '...'
         
     | 
| 
       999 
     | 
    
         
            -
                      .reject(&:empty?)
         
     | 
| 
       1000 
     | 
    
         
            -
             
     | 
| 
       1001 
     | 
    
         
            -
                    # First dot-separated component can match any ancestor or top-level doc
         
     | 
| 
       1002 
     | 
    
         
            -
                    first_part = parts.shift
         
     | 
| 
       1003 
     | 
    
         
            -
                    name_root = ancestor_name_match(first_part, doc) ||
         
     | 
| 
       1004 
     | 
    
         
            -
                                name_match(first_part, root_decls)
         
     | 
| 
       1005 
     | 
    
         
            -
             
     | 
| 
       1006 
     | 
    
         
            -
                    # Traverse children via subsequent components, if any
         
     | 
| 
       1007 
     | 
    
         
            -
                    [name_traversal(parts, name_root), sym_name.sub(%r{^.*/}, '')]
         
     | 
| 
      
 954 
     | 
    
         
            +
                    [@doc_index.lookup(sym_name, doc), sym_name.sub(%r{^.*/}, '')]
         
     | 
| 
       1008 
955 
     | 
    
         
             
                  end.autolink_block(doc.url, '[+-]\[\w+(?: ?\(\w+\))? [\w:]+\]',
         
     | 
| 
       1009 
956 
     | 
    
         
             
                                     after_highlight) do |raw_name|
         
     | 
| 
       1010 
     | 
    
         
            -
                     
     | 
| 
       1011 
     | 
    
         
            -
             
     | 
| 
       1012 
     | 
    
         
            -
                    # Subject component can match any ancestor or top-level doc
         
     | 
| 
       1013 
     | 
    
         
            -
                    subject = match[2].delete(' ')
         
     | 
| 
       1014 
     | 
    
         
            -
                    name_root = ancestor_name_match(subject, doc) ||
         
     | 
| 
       1015 
     | 
    
         
            -
                                name_match(subject, root_decls)
         
     | 
| 
       1016 
     | 
    
         
            -
             
     | 
| 
       1017 
     | 
    
         
            -
                    if name_root
         
     | 
| 
       1018 
     | 
    
         
            -
                      # Look up the verb in the subject’s children
         
     | 
| 
       1019 
     | 
    
         
            -
                      [name_match(match[1] + match[3], name_root.children), raw_name]
         
     | 
| 
       1020 
     | 
    
         
            -
                    end
         
     | 
| 
      
 957 
     | 
    
         
            +
                    [@doc_index.lookup(raw_name, doc), raw_name]
         
     | 
| 
       1021 
958 
     | 
    
         
             
                  end.autolink_block(doc.url, '[+-]\w[\w:]*', after_highlight) do |raw_name|
         
     | 
| 
       1022 
     | 
    
         
            -
                    [ 
     | 
| 
      
 959 
     | 
    
         
            +
                    [@doc_index.lookup(raw_name, doc), raw_name]
         
     | 
| 
       1023 
960 
     | 
    
         
             
                  end
         
     | 
| 
       1024 
961 
     | 
    
         
             
                end
         
     | 
| 
       1025 
     | 
    
         
            -
                # rubocop:enable Metrics/MethodLength
         
     | 
| 
       1026 
962 
     | 
    
         | 
| 
       1027 
963 
     | 
    
         
             
                AUTOLINK_TEXT_FIELDS = %w[return
         
     | 
| 
       1028 
964 
     | 
    
         
             
                                          abstract
         
     | 
| 
       1029 
965 
     | 
    
         
             
                                          unavailable_message
         
     | 
| 
       1030 
966 
     | 
    
         
             
                                          deprecation_message].freeze
         
     | 
| 
       1031 
967 
     | 
    
         | 
| 
       1032 
     | 
    
         
            -
                def self.autolink_text_fields(doc 
     | 
| 
      
 968 
     | 
    
         
            +
                def self.autolink_text_fields(doc)
         
     | 
| 
       1033 
969 
     | 
    
         
             
                  AUTOLINK_TEXT_FIELDS.each do |field|
         
     | 
| 
       1034 
970 
     | 
    
         
             
                    if text = doc.send(field)
         
     | 
| 
       1035 
     | 
    
         
            -
                      doc.send(field + '=', autolink_text(text, doc 
     | 
| 
      
 971 
     | 
    
         
            +
                      doc.send(field + '=', autolink_text(text, doc))
         
     | 
| 
       1036 
972 
     | 
    
         
             
                    end
         
     | 
| 
       1037 
973 
     | 
    
         
             
                  end
         
     | 
| 
       1038 
974 
     | 
    
         | 
| 
       1039 
975 
     | 
    
         
             
                  (doc.parameters || []).each do |param|
         
     | 
| 
       1040 
976 
     | 
    
         
             
                    param[:discussion] =
         
     | 
| 
       1041 
     | 
    
         
            -
                      autolink_text(param[:discussion], doc 
     | 
| 
      
 977 
     | 
    
         
            +
                      autolink_text(param[:discussion], doc)
         
     | 
| 
       1042 
978 
     | 
    
         
             
                  end
         
     | 
| 
       1043 
979 
     | 
    
         
             
                end
         
     | 
| 
       1044 
980 
     | 
    
         | 
| 
       1045 
981 
     | 
    
         
             
                AUTOLINK_HIGHLIGHT_FIELDS = %w[declaration
         
     | 
| 
       1046 
982 
     | 
    
         
             
                                               other_language_declaration].freeze
         
     | 
| 
       1047 
983 
     | 
    
         | 
| 
       1048 
     | 
    
         
            -
                def self.autolink_highlight_fields(doc 
     | 
| 
      
 984 
     | 
    
         
            +
                def self.autolink_highlight_fields(doc)
         
     | 
| 
       1049 
985 
     | 
    
         
             
                  AUTOLINK_HIGHLIGHT_FIELDS.each do |field|
         
     | 
| 
       1050 
986 
     | 
    
         
             
                    if text = doc.send(field)
         
     | 
| 
       1051 
987 
     | 
    
         
             
                      doc.send(field + '=',
         
     | 
| 
       1052 
     | 
    
         
            -
                               autolink_text(text, doc,  
     | 
| 
      
 988 
     | 
    
         
            +
                               autolink_text(text, doc, after_highlight: true))
         
     | 
| 
       1053 
989 
     | 
    
         
             
                    end
         
     | 
| 
       1054 
990 
     | 
    
         
             
                  end
         
     | 
| 
       1055 
991 
     | 
    
         
             
                end
         
     | 
| 
       1056 
992 
     | 
    
         | 
| 
       1057 
     | 
    
         
            -
                def self.autolink(docs 
     | 
| 
       1058 
     | 
    
         
            -
                  @autolink_root_decls = root_decls
         
     | 
| 
      
 993 
     | 
    
         
            +
                def self.autolink(docs)
         
     | 
| 
       1059 
994 
     | 
    
         
             
                  docs.each do |doc|
         
     | 
| 
       1060 
     | 
    
         
            -
                    doc.children = autolink(doc.children 
     | 
| 
       1061 
     | 
    
         
            -
                    autolink_text_fields(doc 
     | 
| 
       1062 
     | 
    
         
            -
                    autolink_highlight_fields(doc 
     | 
| 
      
 995 
     | 
    
         
            +
                    doc.children = autolink(doc.children)
         
     | 
| 
      
 996 
     | 
    
         
            +
                    autolink_text_fields(doc)
         
     | 
| 
      
 997 
     | 
    
         
            +
                    autolink_highlight_fields(doc)
         
     | 
| 
       1063 
998 
     | 
    
         
             
                  end
         
     | 
| 
       1064 
999 
     | 
    
         
             
                end
         
     | 
| 
       1065 
1000 
     | 
    
         | 
| 
       1066 
1001 
     | 
    
         
             
                # For autolinking external markdown documents
         
     | 
| 
       1067 
1002 
     | 
    
         
             
                def self.autolink_document(html, doc)
         
     | 
| 
       1068 
     | 
    
         
            -
                  autolink_text(html, doc 
     | 
| 
      
 1003 
     | 
    
         
            +
                  autolink_text(html, doc)
         
     | 
| 
      
 1004 
     | 
    
         
            +
                end
         
     | 
| 
      
 1005 
     | 
    
         
            +
             
     | 
| 
      
 1006 
     | 
    
         
            +
                #
         
     | 
| 
      
 1007 
     | 
    
         
            +
                # Entrypoint and misc filtering
         
     | 
| 
      
 1008 
     | 
    
         
            +
                #
         
     | 
| 
      
 1009 
     | 
    
         
            +
             
     | 
| 
      
 1010 
     | 
    
         
            +
                # Apply filtering based on the "included" and "excluded" flags.
         
     | 
| 
      
 1011 
     | 
    
         
            +
                def self.filter_files(json)
         
     | 
| 
      
 1012 
     | 
    
         
            +
                  json = filter_included_files(json) if Config.instance.included_files.any?
         
     | 
| 
      
 1013 
     | 
    
         
            +
                  json = filter_excluded_files(json) if Config.instance.excluded_files.any?
         
     | 
| 
      
 1014 
     | 
    
         
            +
                  json.map do |doc|
         
     | 
| 
      
 1015 
     | 
    
         
            +
                    key = doc.keys.first
         
     | 
| 
      
 1016 
     | 
    
         
            +
                    doc[key]
         
     | 
| 
      
 1017 
     | 
    
         
            +
                  end.compact
         
     | 
| 
      
 1018 
     | 
    
         
            +
                end
         
     | 
| 
      
 1019 
     | 
    
         
            +
             
     | 
| 
      
 1020 
     | 
    
         
            +
                # Filter based on the "included" flag.
         
     | 
| 
      
 1021 
     | 
    
         
            +
                def self.filter_included_files(json)
         
     | 
| 
      
 1022 
     | 
    
         
            +
                  included_files = Config.instance.included_files
         
     | 
| 
      
 1023 
     | 
    
         
            +
                  json.map do |doc|
         
     | 
| 
      
 1024 
     | 
    
         
            +
                    key = doc.keys.first
         
     | 
| 
      
 1025 
     | 
    
         
            +
                    doc if included_files.detect do |include|
         
     | 
| 
      
 1026 
     | 
    
         
            +
                      File.fnmatch?(include, key)
         
     | 
| 
      
 1027 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1028 
     | 
    
         
            +
                  end.compact
         
     | 
| 
      
 1029 
     | 
    
         
            +
                end
         
     | 
| 
      
 1030 
     | 
    
         
            +
             
     | 
| 
      
 1031 
     | 
    
         
            +
                # Filter based on the "excluded" flag.
         
     | 
| 
      
 1032 
     | 
    
         
            +
                def self.filter_excluded_files(json)
         
     | 
| 
      
 1033 
     | 
    
         
            +
                  excluded_files = Config.instance.excluded_files
         
     | 
| 
      
 1034 
     | 
    
         
            +
                  json.map do |doc|
         
     | 
| 
      
 1035 
     | 
    
         
            +
                    key = doc.keys.first
         
     | 
| 
      
 1036 
     | 
    
         
            +
                    doc unless excluded_files.detect do |exclude|
         
     | 
| 
      
 1037 
     | 
    
         
            +
                      File.fnmatch?(exclude, key)
         
     | 
| 
      
 1038 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1039 
     | 
    
         
            +
                  end.compact
         
     | 
| 
       1069 
1040 
     | 
    
         
             
                end
         
     | 
| 
       1070 
1041 
     | 
    
         | 
| 
       1071 
1042 
     | 
    
         
             
                def self.reject_objc_types(docs)
         
     | 
| 
         @@ -1083,26 +1054,51 @@ module Jazzy 
     | 
|
| 
       1083 
1054 
     | 
    
         
             
                  end
         
     | 
| 
       1084 
1055 
     | 
    
         
             
                end
         
     | 
| 
       1085 
1056 
     | 
    
         | 
| 
      
 1057 
     | 
    
         
            +
                # Remove top-level enum cases because it means they have an ACL lower
         
     | 
| 
      
 1058 
     | 
    
         
            +
                # than min_acl
         
     | 
| 
      
 1059 
     | 
    
         
            +
                def self.reject_swift_types(docs)
         
     | 
| 
      
 1060 
     | 
    
         
            +
                  docs.reject { |doc| doc.type.swift_enum_element? }
         
     | 
| 
      
 1061 
     | 
    
         
            +
                end
         
     | 
| 
      
 1062 
     | 
    
         
            +
             
     | 
| 
      
 1063 
     | 
    
         
            +
                # Spot and mark any categories on classes not declared in these docs
         
     | 
| 
      
 1064 
     | 
    
         
            +
                def self.mark_objc_external_categories(docs)
         
     | 
| 
      
 1065 
     | 
    
         
            +
                  class_names = docs.select { |doc| doc.type.objc_class? }.to_set(&:name)
         
     | 
| 
      
 1066 
     | 
    
         
            +
             
     | 
| 
      
 1067 
     | 
    
         
            +
                  docs.map do |doc|
         
     | 
| 
      
 1068 
     | 
    
         
            +
                    if (names = doc.objc_category_name) && !class_names.include?(names.first)
         
     | 
| 
      
 1069 
     | 
    
         
            +
                      doc.module_name = '(Imported)'
         
     | 
| 
      
 1070 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1071 
     | 
    
         
            +
                    doc
         
     | 
| 
      
 1072 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1073 
     | 
    
         
            +
                end
         
     | 
| 
      
 1074 
     | 
    
         
            +
             
     | 
| 
       1086 
1075 
     | 
    
         
             
                # Parse sourcekitten STDOUT output as JSON
         
     | 
| 
       1087 
1076 
     | 
    
         
             
                # @return [Hash] structured docs
         
     | 
| 
       1088 
     | 
    
         
            -
                def self.parse(sourcekitten_output,  
     | 
| 
       1089 
     | 
    
         
            -
                  @min_acl = min_acl
         
     | 
| 
       1090 
     | 
    
         
            -
                  @skip_undocumented = skip_undocumented
         
     | 
| 
      
 1077 
     | 
    
         
            +
                def self.parse(sourcekitten_output, options, inject_docs)
         
     | 
| 
      
 1078 
     | 
    
         
            +
                  @min_acl = options.min_acl
         
     | 
| 
      
 1079 
     | 
    
         
            +
                  @skip_undocumented = options.skip_undocumented
         
     | 
| 
       1091 
1080 
     | 
    
         
             
                  @stats = Stats.new
         
     | 
| 
       1092 
1081 
     | 
    
         
             
                  @inaccessible_protocols = []
         
     | 
| 
       1093 
     | 
    
         
            -
             
     | 
| 
       1094 
     | 
    
         
            -
                   
     | 
| 
      
 1082 
     | 
    
         
            +
             
     | 
| 
      
 1083 
     | 
    
         
            +
                  # Process each module separately to inject the source module name
         
     | 
| 
      
 1084 
     | 
    
         
            +
                  docs = sourcekitten_output.zip(options.module_names).map do |json, name|
         
     | 
| 
      
 1085 
     | 
    
         
            +
                    @current_module_name = name
         
     | 
| 
      
 1086 
     | 
    
         
            +
                    sourcekitten_dicts = filter_files(JSON.parse(json).flatten)
         
     | 
| 
      
 1087 
     | 
    
         
            +
                    make_source_declarations(sourcekitten_dicts)
         
     | 
| 
      
 1088 
     | 
    
         
            +
                  end.flatten + inject_docs
         
     | 
| 
      
 1089 
     | 
    
         
            +
             
     | 
| 
       1095 
1090 
     | 
    
         
             
                  docs = expand_extensions(docs)
         
     | 
| 
       1096 
1091 
     | 
    
         
             
                  docs = deduplicate_declarations(docs)
         
     | 
| 
       1097 
1092 
     | 
    
         
             
                  docs = reject_objc_types(docs)
         
     | 
| 
       1098 
     | 
    
         
            -
                   
     | 
| 
       1099 
     | 
    
         
            -
                   
     | 
| 
       1100 
     | 
    
         
            -
             
     | 
| 
       1101 
     | 
    
         
            -
                   
     | 
| 
       1102 
     | 
    
         
            -
             
     | 
| 
       1103 
     | 
    
         
            -
                   
     | 
| 
      
 1093 
     | 
    
         
            +
                  docs = reject_swift_types(docs)
         
     | 
| 
      
 1094 
     | 
    
         
            +
                  docs = mark_objc_external_categories(docs)
         
     | 
| 
      
 1095 
     | 
    
         
            +
             
     | 
| 
      
 1096 
     | 
    
         
            +
                  @doc_index = DocIndex.new(docs)
         
     | 
| 
      
 1097 
     | 
    
         
            +
             
     | 
| 
      
 1098 
     | 
    
         
            +
                  docs = Grouper.group_docs(docs, @doc_index)
         
     | 
| 
      
 1099 
     | 
    
         
            +
             
     | 
| 
       1104 
1100 
     | 
    
         
             
                  make_doc_urls(docs)
         
     | 
| 
       1105 
     | 
    
         
            -
                  autolink(docs 
     | 
| 
      
 1101 
     | 
    
         
            +
                  autolink(docs)
         
     | 
| 
       1106 
1102 
     | 
    
         
             
                  [docs, @stats]
         
     | 
| 
       1107 
1103 
     | 
    
         
             
                end
         
     | 
| 
       1108 
1104 
     | 
    
         
             
              end
         
     |