Module: Jazzy::SourceKitten

Defined in:
lib/jazzy/sourcekitten.rb

Overview

This module interacts with the sourcekitten command-line executable

Class Method Summary collapse

Class Method Details

.doc_coverage(sourcekitten_json) ⇒ Object

rubocop:enable Metrics/MethodLength



148
149
150
151
152
153
154
155
156
157
# File 'lib/jazzy/sourcekitten.rb', line 148

def self.doc_coverage(sourcekitten_json)
  documented = sourcekitten_json
                .map { |el| el['key.doc.documented'] }
                .inject(:+)
  undocumented = sourcekitten_json
                  .map { |el| el['key.doc.undocumented'] }
                  .inject(:+)
  return 0 if documented == 0 && undocumented == 0
  (100 * documented) / (undocumented + documented)
end

.group_docs(docs, kind) ⇒ Object

Group root-level docs by kind and add as children to a group doc element



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/jazzy/sourcekitten.rb', line 38

def self.group_docs(docs, kind)
  kind_name_plural = @kinds[kind].pluralize
  group, docs = docs.partition { |doc| doc.kind == kind }
  docs << SourceDeclaration.new.tap do |sd|
    sd.name = kind_name_plural
    sd.kind = 'Overview'
    sd.abstract = "The following #{kind_name_plural.downcase} are " \
                  'available globally.'
    sd.children = group
  end if group.count > 0
  docs
end

.make_default_doc_info(declaration) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/jazzy/sourcekitten.rb', line 75

def self.make_default_doc_info(declaration)
  # @todo: Fix these
  declaration.line = 0
  declaration.column = 0
  declaration.abstract = 'Undocumented'
  declaration.parameters = []
end

.make_doc_info(doc, declaration) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/jazzy/sourcekitten.rb', line 83

def self.make_doc_info(doc, declaration)
  if doc['key.doc.full_as_xml']
    xml = Nokogiri::XML(doc['key.doc.full_as_xml']).root
    declaration.line = XMLHelper.attribute(xml, 'line').to_i
    declaration.column = XMLHelper.attribute(xml, 'column').to_i
    declaration.declaration = XMLHelper.xpath(xml, 'Declaration')
    declaration.abstract = XMLHelper.xpath(xml, 'Abstract')
    declaration.discussion = XMLHelper.xpath(xml, 'Discussion')
    declaration.return = XMLHelper.xpath(xml, 'ResultDiscussion')

    declaration.parameters = []
    xml.xpath('Parameters/Parameter').each do |parameter_el|
      declaration.parameters << {
        name: XMLHelper.xpath(parameter_el, 'Name'),
        discussion: Jazzy.markdown.render(
            XMLHelper.xpath(parameter_el, 'Discussion'),
          ),
      }
    end
  else
    make_default_doc_info(declaration)
  end
end

.make_doc_urls(docs, parents) ⇒ Hash

Generate doc URL by prepending its parents URLs

Returns:

  • (Hash)

    input docs with URLs



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/jazzy/sourcekitten.rb', line 53

def self.make_doc_urls(docs, parents)
  docs.each do |doc|
    if doc.children.count > 0
      # Create HTML page for this doc if it has children
      parents_slash = parents.count > 0 ? '/' : ''
      doc.url = parents.join('/') + parents_slash + doc.name + '.html'
      doc.children = make_doc_urls(doc.children, parents + [doc.name])
    else
      # Don't create HTML page for this doc if it doesn't have children
      # Instead, make its link a hash-link on its parent's page
      doc.url = parents.join('/') + '.html#/' + doc.usr
    end
  end
  docs
end

.make_source_declarations(docs) ⇒ Object

rubocop:disable Metrics/MethodLength



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/jazzy/sourcekitten.rb', line 118

def self.make_source_declarations(docs)
  declarations = []
  docs.each do |doc|
    if doc.key?('key.diagnostic_stage')
      declarations += make_source_declarations(doc['key.substructure'])
      next
    end
    declaration = SourceDeclaration.new
    declaration.kind = doc['key.kind']
    next unless declaration.kind =~ /^source\.lang\.swift\.decl\..*/

    unless declaration.kindName = @kinds[declaration.kind]
      raise 'Please file an issue on ' \
      'https://github.com/realm/jazzy/issues about adding support for ' \
      "`#{declaration.kind}`"
    end

    declaration.kindNamePlural = declaration.kindName.pluralize
    declaration.file = doc['key.filepath']
    declaration.usr = doc['key.usr']
    declaration.name = doc['key.name']

    make_doc_info(doc, declaration)
    make_substructure(doc, declaration)
    declarations << declaration
  end
  declarations
end

.make_substructure(doc, declaration) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/jazzy/sourcekitten.rb', line 107

def self.make_substructure(doc, declaration)
  if doc['key.substructure']
    declaration.children = make_source_declarations(
      doc['key.substructure'],
    )
  else
    declaration.children = []
  end
end

.parse(sourcekitten_output) ⇒ Hash

Parse sourcekitten STDOUT output as JSON

Returns:

  • (Hash)

    structured docs



161
162
163
164
165
166
167
168
# File 'lib/jazzy/sourcekitten.rb', line 161

def self.parse(sourcekitten_output)
  sourcekitten_json = JSON.parse(sourcekitten_output)
  docs = make_source_declarations(sourcekitten_json)
  @kinds.keys.each do |kind|
    docs = group_docs(docs, kind)
  end
  [make_doc_urls(docs, []), doc_coverage(sourcekitten_json)]
end

.run_sourcekitten(arguments) ⇒ Object

Run sourcekitten with given arguments and return STDOUT



70
71
72
73
# File 'lib/jazzy/sourcekitten.rb', line 70

def self.run_sourcekitten(arguments)
  bin_path = Pathname(__FILE__).parent + '../../bin'
  `#{bin_path}/sourcekitten #{(arguments).join(' ')}`
end