jazzy 0.14.0 → 0.14.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/Tests.yml +5 -5
- data/.rubocop.yml +62 -2
- data/CHANGELOG.md +75 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile.lock +76 -66
- data/ObjectiveC.md +208 -0
- data/README.md +42 -24
- data/Rakefile +5 -3
- data/bin/sourcekitten +0 -0
- data/jazzy.gemspec +2 -1
- data/js/package-lock.json +61 -12
- data/lib/jazzy/config.rb +54 -35
- data/lib/jazzy/doc_builder.rb +9 -2
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- 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/jazzy_markdown.rb +13 -3
- data/lib/jazzy/search_builder.rb +3 -5
- data/lib/jazzy/source_declaration/type.rb +26 -2
- data/lib/jazzy/source_declaration.rb +13 -2
- data/lib/jazzy/sourcekitten.rb +58 -10
- data/lib/jazzy/stats.rb +11 -2
- data/lib/jazzy/symbol_graph/graph.rb +7 -2
- data/lib/jazzy/symbol_graph/relationship.rb +6 -0
- data/lib/jazzy/symbol_graph/sym_node.rb +14 -1
- data/lib/jazzy/symbol_graph/symbol.rb +36 -10
- data/lib/jazzy/symbol_graph.rb +30 -19
- data/lib/jazzy/themes/apple/assets/js/jquery.min.js +2 -2
- data/lib/jazzy/themes/apple/templates/doc.mustache +1 -2
- data/lib/jazzy/themes/apple/templates/footer.mustache +1 -1
- data/lib/jazzy/themes/apple/templates/header.mustache +4 -4
- data/lib/jazzy/themes/apple/templates/task.mustache +3 -8
- data/lib/jazzy/themes/fullwidth/assets/js/jquery.min.js +2 -2
- data/lib/jazzy/themes/fullwidth/templates/doc.mustache +1 -2
- data/lib/jazzy/themes/fullwidth/templates/footer.mustache +1 -1
- data/lib/jazzy/themes/fullwidth/templates/header.mustache +4 -4
- data/lib/jazzy/themes/fullwidth/templates/task.mustache +3 -8
- data/lib/jazzy/themes/jony/assets/js/jquery.min.js +2 -2
- data/lib/jazzy/themes/jony/templates/doc.mustache +1 -2
- data/lib/jazzy/themes/jony/templates/footer.mustache +1 -1
- data/lib/jazzy/themes/jony/templates/header.mustache +2 -2
- data/lib/jazzy/themes/jony/templates/task.mustache +3 -8
- data/spec/integration_spec.rb +18 -13
- metadata +8 -6
data/lib/jazzy/gem_version.rb
CHANGED
data/lib/jazzy/jazzy_markdown.rb
CHANGED
@@ -40,7 +40,8 @@ module Jazzy
|
|
40
40
|
mapped = map_footnote(num)
|
41
41
|
"\n<li><div class='footnote-def' id=\"fn#{mapped}\">" +
|
42
42
|
text.sub(%r{(?=</p>)},
|
43
|
-
" <a href=\"#fnref#{mapped}\">↩</a
|
43
|
+
" <a href=\"#fnref#{mapped}\">↩</a>") +
|
44
|
+
'</div></li>'
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
@@ -66,7 +67,9 @@ module Jazzy
|
|
66
67
|
def codespan(text)
|
67
68
|
case text
|
68
69
|
when /^\$\$(.*)\$\$$/m
|
69
|
-
o = ["
|
70
|
+
o = ["</p><div class='math m-block'>",
|
71
|
+
Regexp.last_match[1],
|
72
|
+
'</div><p>']
|
70
73
|
Markdown.has_math = true
|
71
74
|
when /^\$(.*)\$$/m
|
72
75
|
o = ["<span class='math m-inline'>", Regexp.last_match[1], '</span>']
|
@@ -258,12 +261,19 @@ module Jazzy
|
|
258
261
|
@markdown ||= Redcarpet::Markdown.new(renderer, REDCARPET_OPTIONS)
|
259
262
|
end
|
260
263
|
|
264
|
+
# Produces <p>-delimited block content
|
261
265
|
def self.render(markdown_text, default_language = nil)
|
262
266
|
renderer.reset
|
263
267
|
renderer.default_language = default_language
|
264
268
|
markdown.render(markdown_text)
|
265
269
|
end
|
266
270
|
|
271
|
+
# Produces <span>-delimited inline content
|
272
|
+
def self.render_inline(markdown_text, default_language = nil)
|
273
|
+
render(markdown_text, default_language)
|
274
|
+
.sub(%r{^<p>(.*)</p>$}, '<span>\1</span>')
|
275
|
+
end
|
276
|
+
|
267
277
|
def self.rendered_returns
|
268
278
|
renderer.returns
|
269
279
|
end
|
@@ -275,7 +285,7 @@ module Jazzy
|
|
275
285
|
class JazzyCopyright < Redcarpet::Render::HTML
|
276
286
|
def link(link, _title, content)
|
277
287
|
%(<a class="link" href="#{link}" target="_blank" \
|
278
|
-
rel="noopener"
|
288
|
+
rel="external noopener">#{content}</a>)
|
279
289
|
end
|
280
290
|
end
|
281
291
|
|
data/lib/jazzy/search_builder.rb
CHANGED
@@ -6,17 +6,15 @@ module Jazzy
|
|
6
6
|
decls = source_module.all_declarations.select do |d|
|
7
7
|
d.type && d.name && !d.name.empty?
|
8
8
|
end
|
9
|
-
index = decls.
|
9
|
+
index = decls.to_h do |d|
|
10
10
|
[d.url,
|
11
11
|
{
|
12
12
|
name: d.name,
|
13
13
|
abstract: d.abstract && d.abstract.split(/\n/).map(&:strip).first,
|
14
|
-
parent_name: d.parent_in_code
|
14
|
+
parent_name: d.parent_in_code&.name,
|
15
15
|
}.reject { |_, v| v.nil? || v.empty? }]
|
16
|
-
end.to_h
|
17
|
-
File.open(File.join(output_dir, 'search.json'), 'w') do |f|
|
18
|
-
f.write(index.to_json)
|
19
16
|
end
|
17
|
+
File.write(File.join(output_dir, 'search.json'), index.to_json)
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -12,11 +12,24 @@ module Jazzy
|
|
12
12
|
|
13
13
|
attr_reader :kind
|
14
14
|
|
15
|
-
def initialize(kind)
|
15
|
+
def initialize(kind, declaration = nil)
|
16
|
+
kind = fixup_kind(kind, declaration) if declaration
|
16
17
|
@kind = kind
|
17
18
|
@type = TYPES[kind]
|
18
19
|
end
|
19
20
|
|
21
|
+
# Improve kind from full declaration
|
22
|
+
def fixup_kind(kind, declaration)
|
23
|
+
if kind == 'source.lang.swift.decl.class' &&
|
24
|
+
declaration.include?(
|
25
|
+
'<syntaxtype.keyword>actor</syntaxtype.keyword>',
|
26
|
+
)
|
27
|
+
'source.lang.swift.decl.actor'
|
28
|
+
else
|
29
|
+
kind
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
20
33
|
def dash_type
|
21
34
|
@type && @type[:dash]
|
22
35
|
end
|
@@ -115,7 +128,8 @@ module Jazzy
|
|
115
128
|
end
|
116
129
|
|
117
130
|
def swift_extensible?
|
118
|
-
kind =~
|
131
|
+
kind =~
|
132
|
+
/^source\.lang\.swift\.decl\.(class|struct|protocol|enum|actor)$/
|
119
133
|
end
|
120
134
|
|
121
135
|
def swift_protocol?
|
@@ -255,6 +269,11 @@ module Jazzy
|
|
255
269
|
dash: 'Struct',
|
256
270
|
global: true,
|
257
271
|
}.freeze,
|
272
|
+
'sourcekitten.source.lang.objc.decl.union' => {
|
273
|
+
jazzy: 'Union',
|
274
|
+
dash: 'Union',
|
275
|
+
global: true,
|
276
|
+
}.freeze,
|
258
277
|
'sourcekitten.source.lang.objc.decl.field' => {
|
259
278
|
jazzy: 'Field',
|
260
279
|
dash: 'Field',
|
@@ -269,6 +288,11 @@ module Jazzy
|
|
269
288
|
}.freeze,
|
270
289
|
|
271
290
|
# Swift
|
291
|
+
'source.lang.swift.decl.actor' => {
|
292
|
+
jazzy: 'Actor',
|
293
|
+
dash: 'Actor',
|
294
|
+
global: true,
|
295
|
+
}.freeze,
|
272
296
|
'source.lang.swift.decl.function.accessor.address' => {
|
273
297
|
jazzy: 'Addressor',
|
274
298
|
dash: 'Function',
|
@@ -138,6 +138,7 @@ module Jazzy
|
|
138
138
|
attr_accessor :unavailable_message
|
139
139
|
attr_accessor :generic_requirements
|
140
140
|
attr_accessor :inherited_types
|
141
|
+
attr_accessor :async
|
141
142
|
|
142
143
|
def usage_discouraged?
|
143
144
|
unavailable || deprecated
|
@@ -182,10 +183,20 @@ module Jazzy
|
|
182
183
|
inherited_types.any? { |t| !unwanted.include?(t) }
|
183
184
|
end
|
184
185
|
|
185
|
-
# SourceKit only sets modulename for imported modules
|
186
|
+
# Pre-Swift 5.6: SourceKit only sets modulename for imported modules
|
187
|
+
# Swift 5.6+: modulename is always set
|
186
188
|
def type_from_doc_module?
|
187
189
|
!type.extension? ||
|
188
|
-
(swift? && usr &&
|
190
|
+
(swift? && usr &&
|
191
|
+
(modulename.nil? || modulename == Config.instance.module_name))
|
192
|
+
end
|
193
|
+
|
194
|
+
# Info text for contents page by collapsed item name
|
195
|
+
def declaration_note
|
196
|
+
notes = [default_impl_abstract ? 'default implementation' : nil,
|
197
|
+
from_protocol_extension ? 'extension method' : nil,
|
198
|
+
async ? 'asynchronous' : nil].compact
|
199
|
+
notes.join(', ').humanize unless notes.empty?
|
189
200
|
end
|
190
201
|
|
191
202
|
def alternative_abstract
|
data/lib/jazzy/sourcekitten.rb
CHANGED
@@ -277,12 +277,18 @@ module Jazzy
|
|
277
277
|
declaration.children = []
|
278
278
|
end
|
279
279
|
|
280
|
+
def self.attribute?(doc, attr_name)
|
281
|
+
doc['key.attributes']&.find do |attribute|
|
282
|
+
attribute['key.attribute'] == "source.decl.attribute.#{attr_name}"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
280
286
|
def self.availability_attribute?(doc)
|
281
|
-
|
287
|
+
attribute?(doc, 'available')
|
288
|
+
end
|
282
289
|
|
283
|
-
|
284
|
-
|
285
|
-
end.empty?
|
290
|
+
def self.spi_attribute?(doc)
|
291
|
+
attribute?(doc, '_spi')
|
286
292
|
end
|
287
293
|
|
288
294
|
def self.should_document?(doc)
|
@@ -302,10 +308,31 @@ module Jazzy
|
|
302
308
|
return false
|
303
309
|
end
|
304
310
|
|
305
|
-
#
|
311
|
+
# Only document @_spi declarations in some scenarios
|
312
|
+
return false unless should_document_spi?(doc)
|
313
|
+
|
314
|
+
# Don't document declarations excluded by the min_acl setting
|
315
|
+
if type.swift_extension?
|
316
|
+
should_document_swift_extension?(doc)
|
317
|
+
else
|
318
|
+
should_document_acl?(type, doc)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# Check visibility: SPI
|
323
|
+
def self.should_document_spi?(doc)
|
324
|
+
spi_ok = @min_acl < SourceDeclaration::AccessControlLevel.public ||
|
325
|
+
Config.instance.include_spi_declarations ||
|
326
|
+
(!spi_attribute?(doc) && !doc['key.symgraph_spi'])
|
327
|
+
|
328
|
+
@stats.add_spi_skipped unless spi_ok
|
329
|
+
spi_ok
|
330
|
+
end
|
331
|
+
|
332
|
+
# Check visibility: access control
|
333
|
+
def self.should_document_acl?(type, doc)
|
334
|
+
# Include all enum elements for now, can't tell their ACL.
|
306
335
|
return true if type.swift_enum_element?
|
307
|
-
# Document extensions if they might have parts covered by the ACL.
|
308
|
-
return should_document_swift_extension?(doc) if type.swift_extension?
|
309
336
|
|
310
337
|
acl_ok = SourceDeclaration::AccessControlLevel.from_doc(doc) >= @min_acl
|
311
338
|
unless acl_ok
|
@@ -315,6 +342,8 @@ module Jazzy
|
|
315
342
|
acl_ok
|
316
343
|
end
|
317
344
|
|
345
|
+
# Document extensions if they add protocol conformances, or have any
|
346
|
+
# member that needs to be documented.
|
318
347
|
def self.should_document_swift_extension?(doc)
|
319
348
|
doc['key.inheritedtypes'] ||
|
320
349
|
Array(doc['key.substructure']).any? do |subdoc|
|
@@ -326,7 +355,9 @@ module Jazzy
|
|
326
355
|
# Call things undocumented if they were compiled properly
|
327
356
|
# and came from our module.
|
328
357
|
def self.should_mark_undocumented(declaration)
|
329
|
-
declaration.usr &&
|
358
|
+
declaration.usr &&
|
359
|
+
(declaration.modulename.nil? ||
|
360
|
+
declaration.modulename == Config.instance.module_name)
|
330
361
|
end
|
331
362
|
|
332
363
|
def self.process_undocumented_token(doc, declaration)
|
@@ -495,6 +526,14 @@ module Jazzy
|
|
495
526
|
.join("\n")
|
496
527
|
end
|
497
528
|
|
529
|
+
# Exclude non-async routines that accept async closures
|
530
|
+
def self.swift_async?(fully_annotated_decl)
|
531
|
+
document = REXML::Document.new(fully_annotated_decl)
|
532
|
+
!document.elements['/*/syntaxtype.keyword[text()="async"]'].nil?
|
533
|
+
rescue StandardError
|
534
|
+
nil
|
535
|
+
end
|
536
|
+
|
498
537
|
# Strip default property attributes because libclang
|
499
538
|
# adds them all, even if absent in the original source code.
|
500
539
|
DEFAULT_ATTRIBUTES = %w[atomic readwrite assign unsafe_unretained].freeze
|
@@ -536,7 +575,9 @@ module Jazzy
|
|
536
575
|
end
|
537
576
|
declaration = SourceDeclaration.new
|
538
577
|
declaration.parent_in_code = parent
|
539
|
-
declaration.type =
|
578
|
+
declaration.type =
|
579
|
+
SourceDeclaration::Type.new(doc['key.kind'],
|
580
|
+
doc['key.fully_annotated_decl'])
|
540
581
|
declaration.typename = doc['key.typename']
|
541
582
|
declaration.objc_name = doc['key.name']
|
542
583
|
documented_name = if Config.instance.hide_objc? && doc['key.swift_name']
|
@@ -581,6 +622,11 @@ module Jazzy
|
|
581
622
|
inherited_types = doc['key.inheritedtypes'] || []
|
582
623
|
declaration.inherited_types =
|
583
624
|
inherited_types.map { |type| type['key.name'] }.compact
|
625
|
+
declaration.async =
|
626
|
+
doc['key.symgraph_async'] ||
|
627
|
+
if xml_declaration = doc['key.fully_annotated_decl']
|
628
|
+
swift_async?(xml_declaration)
|
629
|
+
end
|
584
630
|
|
585
631
|
next unless make_doc_info(doc, declaration)
|
586
632
|
|
@@ -790,7 +836,9 @@ module Jazzy
|
|
790
836
|
extensions.each do |ext|
|
791
837
|
ext.children = ext.children.select do |ext_member|
|
792
838
|
proto_member = protocol.children.find do |p|
|
793
|
-
p.name == ext_member.name &&
|
839
|
+
p.name == ext_member.name &&
|
840
|
+
p.type == ext_member.type &&
|
841
|
+
p.async == ext_member.async
|
794
842
|
end
|
795
843
|
|
796
844
|
# Extension-only method, keep.
|
data/lib/jazzy/stats.rb
CHANGED
@@ -5,7 +5,7 @@ module Jazzy
|
|
5
5
|
class Stats
|
6
6
|
include Config::Mixin
|
7
7
|
|
8
|
-
attr_reader :documented, :acl_skipped, :undocumented_decls
|
8
|
+
attr_reader :documented, :acl_skipped, :spi_skipped, :undocumented_decls
|
9
9
|
|
10
10
|
def add_documented
|
11
11
|
@documented += 1
|
@@ -15,6 +15,10 @@ module Jazzy
|
|
15
15
|
@acl_skipped += 1
|
16
16
|
end
|
17
17
|
|
18
|
+
def add_spi_skipped
|
19
|
+
@spi_skipped += 1
|
20
|
+
end
|
21
|
+
|
18
22
|
def add_undocumented(decl)
|
19
23
|
@undocumented_decls << decl
|
20
24
|
end
|
@@ -32,7 +36,7 @@ module Jazzy
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def initialize
|
35
|
-
@documented = @acl_skipped = 0
|
39
|
+
@documented = @acl_skipped = @spi_skipped = 0
|
36
40
|
@undocumented_decls = []
|
37
41
|
end
|
38
42
|
|
@@ -54,6 +58,11 @@ module Jazzy
|
|
54
58
|
"#{symbol_or_symbols(acl_skipped)} " \
|
55
59
|
'(use `--min-acl` to specify a different minimum ACL)'
|
56
60
|
end
|
61
|
+
|
62
|
+
if spi_skipped > 0
|
63
|
+
puts "skipped #{spi_skipped} SPI #{symbol_or_symbols(spi_skipped)} " \
|
64
|
+
'(use `--include-spi-declarations` to include these)'
|
65
|
+
end
|
57
66
|
end
|
58
67
|
|
59
68
|
def doc_coverage
|
@@ -78,8 +78,13 @@ module Jazzy
|
|
78
78
|
|
79
79
|
# Protocol conformance is redundant if it's unconditional
|
80
80
|
# and already expressed in the type's declaration.
|
81
|
+
#
|
82
|
+
# Skip implementation-detail conformances.
|
81
83
|
def redundant_conformance?(rel, type, protocol)
|
82
|
-
|
84
|
+
return false unless type
|
85
|
+
|
86
|
+
(rel.constraints.empty? && type.conformance?(protocol)) ||
|
87
|
+
(type.actor? && rel.actor_protocol?)
|
83
88
|
end
|
84
89
|
|
85
90
|
# source is a member/protocol requirement of target
|
@@ -123,7 +128,7 @@ module Jazzy
|
|
123
128
|
(target_parent = target.parent) &&
|
124
129
|
target_parent.is_a?(SymNode)
|
125
130
|
# Could probably figure this out with demangle, but...
|
126
|
-
warn "Can't resolve membership of default implementation "\
|
131
|
+
warn "Can't resolve membership of default implementation " \
|
127
132
|
"#{source.symbol.usr}."
|
128
133
|
source.unlisted = true
|
129
134
|
return
|
@@ -22,6 +22,12 @@ module Jazzy
|
|
22
22
|
kind == :defaultImplementationOf
|
23
23
|
end
|
24
24
|
|
25
|
+
# Protocol conformances added by compiler to actor decls that
|
26
|
+
# users aren't interested in.
|
27
|
+
def actor_protocol?
|
28
|
+
%w[Actor Sendable].include?(target_fallback)
|
29
|
+
end
|
30
|
+
|
25
31
|
def initialize(hash)
|
26
32
|
kind = hash[:kind]
|
27
33
|
unless KINDS.include?(kind)
|
@@ -25,6 +25,7 @@ module Jazzy
|
|
25
25
|
|
26
26
|
# A SymNode is a node of the reconstructed syntax tree holding a symbol.
|
27
27
|
# It can turn itself into SourceKit and helps decode extensions.
|
28
|
+
# rubocop:disable Metrics/ClassLength
|
28
29
|
class SymNode < BaseNode
|
29
30
|
attr_accessor :symbol
|
30
31
|
attr_writer :override
|
@@ -61,6 +62,10 @@ module Jazzy
|
|
61
62
|
symbol.kind.end_with?('protocol')
|
62
63
|
end
|
63
64
|
|
65
|
+
def actor?
|
66
|
+
symbol.kind.end_with?('actor')
|
67
|
+
end
|
68
|
+
|
64
69
|
def constraints
|
65
70
|
symbol.constraints
|
66
71
|
end
|
@@ -112,8 +117,13 @@ module Jazzy
|
|
112
117
|
" : #{superclass_name}"
|
113
118
|
end
|
114
119
|
|
120
|
+
# approximately...
|
121
|
+
def async?
|
122
|
+
symbol.declaration =~ /\basync\b[^)]*$/
|
123
|
+
end
|
124
|
+
|
115
125
|
def full_declaration
|
116
|
-
symbol.
|
126
|
+
symbol.attributes
|
117
127
|
.append(symbol.declaration + inherits_clause + where_clause)
|
118
128
|
.join("\n")
|
119
129
|
end
|
@@ -130,6 +140,7 @@ module Jazzy
|
|
130
140
|
'key.accessibility' => symbol.acl,
|
131
141
|
'key.parsed_decl' => declaration,
|
132
142
|
'key.annotated_decl' => xml_declaration,
|
143
|
+
'key.symgraph_async' => async?,
|
133
144
|
}
|
134
145
|
if docs = symbol.doc_comments
|
135
146
|
hash['key.doc.comment'] = docs
|
@@ -147,6 +158,7 @@ module Jazzy
|
|
147
158
|
unless children.empty?
|
148
159
|
hash['key.substructure'] = children_to_sourcekit
|
149
160
|
end
|
161
|
+
hash['key.symgraph_spi'] = true if symbol.spi
|
150
162
|
|
151
163
|
hash
|
152
164
|
end
|
@@ -159,5 +171,6 @@ module Jazzy
|
|
159
171
|
symbol <=> other.symbol
|
160
172
|
end
|
161
173
|
end
|
174
|
+
# rubocop:enable Metrics/ClassLength
|
162
175
|
end
|
163
176
|
end
|
@@ -10,10 +10,11 @@ module Jazzy
|
|
10
10
|
attr_accessor :declaration
|
11
11
|
attr_accessor :kind
|
12
12
|
attr_accessor :acl
|
13
|
+
attr_accessor :spi
|
13
14
|
attr_accessor :location # can be nil, keys :filename :line :character
|
14
15
|
attr_accessor :constraints # array, can be empty
|
15
16
|
attr_accessor :doc_comments # can be nil
|
16
|
-
attr_accessor :
|
17
|
+
attr_accessor :attributes # array, can be empty
|
17
18
|
attr_accessor :generic_type_params # set, can be empty
|
18
19
|
attr_accessor :parameter_names # array, can be nil
|
19
20
|
|
@@ -24,13 +25,14 @@ module Jazzy
|
|
24
25
|
def initialize(hash)
|
25
26
|
self.usr = hash[:identifier][:precise]
|
26
27
|
self.path_components = hash[:pathComponents]
|
27
|
-
raw_decl = hash[:declarationFragments]
|
28
|
-
init_kind(hash[:kind][:identifier])
|
28
|
+
raw_decl, keywords = parse_decl_fragments(hash[:declarationFragments])
|
29
|
+
init_kind(hash[:kind][:identifier], keywords)
|
29
30
|
init_declaration(raw_decl)
|
30
31
|
if func_signature = hash[:functionSignature]
|
31
32
|
init_func_signature(func_signature)
|
32
33
|
end
|
33
34
|
init_acl(hash[:accessLevel])
|
35
|
+
self.spi = hash[:spi]
|
34
36
|
if location = hash[:location]
|
35
37
|
init_location(location)
|
36
38
|
end
|
@@ -38,10 +40,20 @@ module Jazzy
|
|
38
40
|
if comments_hash = hash[:docComment]
|
39
41
|
init_doc_comments(comments_hash)
|
40
42
|
end
|
41
|
-
|
43
|
+
init_attributes(hash[:availability] || [])
|
42
44
|
init_generic_type_params(hash)
|
43
45
|
end
|
44
46
|
|
47
|
+
def parse_decl_fragments(fragments)
|
48
|
+
decl = ''
|
49
|
+
keywords = Set.new
|
50
|
+
fragments.each do |frag|
|
51
|
+
decl += frag[:spelling]
|
52
|
+
keywords.add(frag[:spelling]) if frag[:kind] == 'keyword'
|
53
|
+
end
|
54
|
+
[decl, keywords]
|
55
|
+
end
|
56
|
+
|
45
57
|
# Repair problems with SymbolGraph's declprinter
|
46
58
|
|
47
59
|
def init_declaration(raw_decl)
|
@@ -87,17 +99,22 @@ module Jazzy
|
|
87
99
|
'static.subscript' => 'function.subscript',
|
88
100
|
'typealias' => 'typealias',
|
89
101
|
'associatedtype' => 'associatedtype',
|
102
|
+
'actor' => 'actor',
|
90
103
|
}.freeze
|
91
104
|
|
92
105
|
# We treat 'static var' differently to 'class var'
|
93
|
-
|
94
|
-
|
106
|
+
# We treat actors as first-class entities
|
107
|
+
def adjust_kind_for_declaration(kind, keywords)
|
108
|
+
if kind == 'swift.class' && keywords.member?('actor')
|
109
|
+
return 'swift.actor'
|
110
|
+
end
|
111
|
+
return kind unless keywords.member?('static')
|
95
112
|
|
96
113
|
kind.gsub(/type/, 'static')
|
97
114
|
end
|
98
115
|
|
99
|
-
def init_kind(kind)
|
100
|
-
adjusted = adjust_kind_for_declaration(kind)
|
116
|
+
def init_kind(kind, keywords)
|
117
|
+
adjusted = adjust_kind_for_declaration(kind, keywords)
|
101
118
|
sourcekit_kind = KIND_MAP[adjusted.sub('swift.', '')]
|
102
119
|
raise "Unknown symbol kind '#{kind}'" unless sourcekit_kind
|
103
120
|
|
@@ -159,8 +176,8 @@ module Jazzy
|
|
159
176
|
# Availability
|
160
177
|
# Re-encode this as Swift. Should really teach Jazzy about these,
|
161
178
|
# could maybe then do something smarter here.
|
162
|
-
def
|
163
|
-
|
179
|
+
def availability_attributes(avail_hash_list)
|
180
|
+
avail_hash_list.map do |avail|
|
164
181
|
str = '@available('
|
165
182
|
if avail[:isUnconditionallyDeprecated]
|
166
183
|
str += '*, deprecated'
|
@@ -190,6 +207,15 @@ module Jazzy
|
|
190
207
|
str
|
191
208
|
end
|
192
209
|
|
210
|
+
def spi_attributes
|
211
|
+
spi ? ['@_spi(Unknown)'] : []
|
212
|
+
end
|
213
|
+
|
214
|
+
def init_attributes(avail_hash_list)
|
215
|
+
self.attributes =
|
216
|
+
availability_attributes(avail_hash_list) + spi_attributes
|
217
|
+
end
|
218
|
+
|
193
219
|
# Sort order
|
194
220
|
include Comparable
|
195
221
|
|
data/lib/jazzy/symbol_graph.rb
CHANGED
@@ -14,27 +14,24 @@ require 'jazzy/symbol_graph/ext_node'
|
|
14
14
|
|
15
15
|
module Jazzy
|
16
16
|
module SymbolGraph
|
17
|
-
#
|
18
|
-
#
|
17
|
+
# Find swift symbol graph files, either having been passed
|
18
|
+
# in directly, or generated by running`swift symbolgraph-extract`
|
19
|
+
# with configured args.
|
20
|
+
# Then parse the results, and return as JSON in SourceKit[ten]
|
19
21
|
# format.
|
20
22
|
def self.build(config)
|
21
|
-
|
22
|
-
|
23
|
+
if config.symbolgraph_directory.nil?
|
24
|
+
Dir.mktmpdir do |tmp_dir|
|
25
|
+
args = arguments(config, tmp_dir)
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
Executable.execute_command('swift',
|
28
|
+
args.unshift('symbolgraph-extract'),
|
29
|
+
true) # raise on error
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
module_name = Regexp.last_match[3] || Regexp.last_match[1]
|
33
|
-
{
|
34
|
-
filename =>
|
35
|
-
Graph.new(File.read(filename), module_name).to_sourcekit,
|
36
|
-
}
|
37
|
-
end.to_json
|
31
|
+
parse_symbols(tmp_dir)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
parse_symbols(config.symbolgraph_directory.to_s)
|
38
35
|
end
|
39
36
|
end
|
40
37
|
|
@@ -47,8 +44,8 @@ module Jazzy
|
|
47
44
|
user_args = config.build_tool_arguments.join
|
48
45
|
|
49
46
|
if user_args =~ /-(?:module-name|minimum-access-level|output-dir)/
|
50
|
-
raise 'error: `--build-tool-arguments` for '\
|
51
|
-
"`--swift-build-tool symbolgraph` can't use `-module`, "\
|
47
|
+
raise 'error: `--build-tool-arguments` for ' \
|
48
|
+
"`--swift-build-tool symbolgraph` can't use `-module`, " \
|
52
49
|
'`-minimum-access-level`, or `-output-dir`.'
|
53
50
|
end
|
54
51
|
|
@@ -69,6 +66,20 @@ module Jazzy
|
|
69
66
|
args + config.build_tool_arguments
|
70
67
|
end
|
71
68
|
|
69
|
+
# Parse the symbol files in the given directory
|
70
|
+
def self.parse_symbols(directory)
|
71
|
+
Dir[directory + '/*.symbols.json'].map do |filename|
|
72
|
+
# The @ part is for extensions in our module (before the @)
|
73
|
+
# of types in another module (after the @).
|
74
|
+
File.basename(filename) =~ /(.*?)(@(.*?))?\.symbols/
|
75
|
+
module_name = Regexp.last_match[3] || Regexp.last_match[1]
|
76
|
+
{
|
77
|
+
filename =>
|
78
|
+
Graph.new(File.read(filename), module_name).to_sourcekit,
|
79
|
+
}
|
80
|
+
end.to_json
|
81
|
+
end
|
82
|
+
|
72
83
|
# Get the SDK path. On !darwin this just isn't needed.
|
73
84
|
def self.sdk(config)
|
74
85
|
`xcrun --show-sdk-path --sdk #{config.sdk}`.chomp
|