jazzy 0.14.3 → 0.14.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Jazzy
4
- VERSION = '0.14.3' unless defined? Jazzy::VERSION
4
+ VERSION = '0.14.4' unless defined? Jazzy::VERSION
5
5
  end
@@ -10,7 +10,7 @@ module Jazzy
10
10
  [d.url,
11
11
  {
12
12
  name: d.name,
13
- abstract: d.abstract && d.abstract.split(/\n/).map(&:strip).first,
13
+ abstract: d.abstract && d.abstract.split("\n").map(&:strip).first,
14
14
  parent_name: d.parent_in_code&.name,
15
15
  }.reject { |_, v| v.nil? || v.empty? }]
16
16
  end
@@ -5,106 +5,94 @@ module Jazzy
5
5
  class AccessControlLevel
6
6
  include Comparable
7
7
 
8
+ # Order matters
9
+ LEVELS = %i[private fileprivate internal package public open].freeze
10
+
11
+ LEVELS_INDEX = LEVELS.to_h { |i| [i, LEVELS.index(i)] }.freeze
12
+
8
13
  attr_reader :level
9
14
 
10
- ACCESSIBILITY_PRIVATE = 'source.lang.swift.accessibility.private'
11
- ACCESSIBILITY_FILEPRIVATE =
12
- 'source.lang.swift.accessibility.fileprivate'
13
- ACCESSIBILITY_INTERNAL = 'source.lang.swift.accessibility.internal'
14
- ACCESSIBILITY_PUBLIC = 'source.lang.swift.accessibility.public'
15
- ACCESSIBILITY_OPEN = 'source.lang.swift.accessibility.open'
16
-
17
- def initialize(accessibility)
18
- @level = case accessibility
19
- when ACCESSIBILITY_PRIVATE then :private
20
- when ACCESSIBILITY_FILEPRIVATE then :fileprivate
21
- when ACCESSIBILITY_INTERNAL then :internal
22
- when ACCESSIBILITY_PUBLIC then :public
23
- when ACCESSIBILITY_OPEN then :open
24
- else
25
- raise 'cannot initialize AccessControlLevel with ' \
26
- "'#{accessibility}'"
27
- end
15
+ def initialize(level)
16
+ @level = level
17
+ end
18
+
19
+ # From a SourceKit accessibility string
20
+ def self.from_accessibility(accessibility)
21
+ return nil if accessibility.nil?
22
+
23
+ if accessibility =~ /^source\.lang\.swift\.accessibility\.(.*)$/ &&
24
+ (matched = Regexp.last_match(1).to_sym) &&
25
+ !LEVELS_INDEX[matched].nil?
26
+ return new(matched)
27
+ end
28
+
29
+ raise "cannot initialize AccessControlLevel with '#{accessibility}'"
28
30
  end
29
31
 
32
+ # From a SourceKit declaration hash
30
33
  def self.from_doc(doc)
31
34
  return AccessControlLevel.internal if implicit_deinit?(doc)
32
35
 
33
- accessibility = doc['key.accessibility']
34
- if accessibility
35
- acl = new(accessibility)
36
- if acl
37
- return acl
38
- end
39
- end
40
- acl = from_doc_explicit_declaration(doc)
41
- acl || AccessControlLevel.internal # fallback on internal ACL
36
+ from_documentation_attribute(doc) ||
37
+ from_accessibility(doc['key.accessibility']) ||
38
+ from_doc_explicit_declaration(doc) ||
39
+ AccessControlLevel.internal # fallback on internal ACL
42
40
  end
43
41
 
42
+ # Workaround `deinit` being always technically public
44
43
  def self.implicit_deinit?(doc)
45
44
  doc['key.name'] == 'deinit' &&
46
45
  from_doc_explicit_declaration(doc).nil?
47
46
  end
48
47
 
48
+ # From a Swift declaration
49
49
  def self.from_doc_explicit_declaration(doc)
50
- case doc['key.parsed_declaration']
51
- when /private\ / then private
52
- when /fileprivate\ / then fileprivate
53
- when /public\ / then public
54
- when /open\ / then open
55
- when /internal\ / then internal
50
+ declaration = doc['key.parsed_declaration']
51
+ LEVELS.each do |level|
52
+ if declaration =~ /\b#{level}\b/
53
+ return send(level)
54
+ end
56
55
  end
56
+ nil
57
57
  end
58
58
 
59
+ # From a config instruction
59
60
  def self.from_human_string(string)
60
- case string.to_s.downcase
61
- when 'private' then private
62
- when 'fileprivate' then fileprivate
63
- when 'internal' then internal
64
- when 'public' then public
65
- when 'open' then open
66
- else raise "cannot initialize AccessControlLevel with '#{string}'"
61
+ normalized = string.to_s.downcase.to_sym
62
+ if LEVELS_INDEX[normalized].nil?
63
+ raise "cannot initialize AccessControlLevel with '#{string}'"
67
64
  end
68
- end
69
-
70
- def self.private
71
- new(ACCESSIBILITY_PRIVATE)
72
- end
73
65
 
74
- def self.fileprivate
75
- new(ACCESSIBILITY_FILEPRIVATE)
66
+ send(normalized)
76
67
  end
77
68
 
78
- def self.internal
79
- new(ACCESSIBILITY_INTERNAL)
69
+ # From a @_documentation(visibility:) attribute
70
+ def self.from_documentation_attribute(doc)
71
+ if doc['key.annotated_decl'] =~ /@_documentation\(\s*visibility\s*:\s*(\w+)/
72
+ from_human_string(Regexp.last_match[1])
73
+ end
80
74
  end
81
75
 
82
- def self.public
83
- new(ACCESSIBILITY_PUBLIC)
84
- end
76
+ # Define `AccessControlLevel.public` etc.
85
77
 
86
- def self.open
87
- new(ACCESSIBILITY_OPEN)
78
+ LEVELS.each do |level|
79
+ define_singleton_method(level) do
80
+ new(level)
81
+ end
88
82
  end
89
83
 
90
- LEVELS = {
91
- private: 0,
92
- fileprivate: 1,
93
- internal: 2,
94
- public: 3,
95
- open: 4,
96
- }.freeze
84
+ # Comparing access levels
97
85
 
98
86
  def <=>(other)
99
- LEVELS[level] <=> LEVELS[other.level]
87
+ LEVELS_INDEX[level] <=> LEVELS_INDEX[other.level]
100
88
  end
101
89
 
102
90
  def included_levels
103
- LEVELS.select { |_, v| v >= LEVELS[level] }.keys
91
+ LEVELS_INDEX.select { |_, v| v >= LEVELS_INDEX[level] }.keys
104
92
  end
105
93
 
106
94
  def excluded_levels
107
- LEVELS.select { |_, v| v < LEVELS[level] }.keys
95
+ LEVELS_INDEX.select { |_, v| v < LEVELS_INDEX[level] }.keys
108
96
  end
109
97
  end
110
98
  end
@@ -456,6 +456,10 @@ module Jazzy
456
456
  jazzy: 'Associated Type',
457
457
  dash: 'Alias',
458
458
  }.freeze,
459
+ 'source.lang.swift.decl.macro' => {
460
+ jazzy: 'Macro',
461
+ dash: 'Macro',
462
+ }.freeze,
459
463
  }.freeze
460
464
  end
461
465
  # rubocop:enable Metrics/ClassLength
@@ -458,6 +458,13 @@ module Jazzy
458
458
  attrs.map { |str| str.gsub(/\)(?!\s*$)/, "\ufe5a") }
459
459
  end
460
460
 
461
+ # Keep everything except instructions to us
462
+ def self.extract_documented_attributes(declaration)
463
+ extract_attributes(declaration).reject do |attr|
464
+ attr.start_with?('@_documentation')
465
+ end
466
+ end
467
+
461
468
  def self.extract_availability(declaration)
462
469
  extract_attributes(declaration, 'available')
463
470
  end
@@ -521,7 +528,7 @@ module Jazzy
521
528
 
522
529
  # @available attrs only in compiler 'interface' style
523
530
  extract_availability(doc['key.doc.declaration'] || '')
524
- .concat(extract_attributes(annotated_decl_attrs))
531
+ .concat(extract_documented_attributes(annotated_decl_attrs))
525
532
  .push(decl)
526
533
  .join("\n")
527
534
  end
@@ -603,6 +610,14 @@ module Jazzy
603
610
  "for `#{declaration.type.kind}`."
604
611
  end
605
612
 
613
+ unless documented_name
614
+ warn 'Found a declaration without `key.name` that will be ' \
615
+ 'ignored. Documentation may be incomplete. This is probably ' \
616
+ 'caused by unresolved compiler errors: check the sourcekitten ' \
617
+ 'output for error messages.'
618
+ next
619
+ end
620
+
606
621
  declaration.file = Pathname(doc['key.filepath']) if doc['key.filepath']
607
622
  declaration.usr = doc['key.usr']
608
623
  declaration.type_usr = doc['key.typeusr']
data/lib/jazzy/stats.rb CHANGED
@@ -41,7 +41,7 @@ module Jazzy
41
41
  end
42
42
 
43
43
  def report
44
- puts "#{doc_coverage}\% documentation coverage " \
44
+ puts "#{doc_coverage}% documentation coverage " \
45
45
  "with #{undocumented} undocumented " \
46
46
  "#{symbol_or_symbols(undocumented)}"
47
47
 
@@ -70,8 +70,13 @@ module Jazzy
70
70
  end.compact
71
71
  end
72
72
 
73
- # Workaround Swift 5.3 bug with missing constraint rels
73
+ # Workaround Swift 5.3 bug with missing constraint rels, eg.
74
+ # extension P {
75
+ # func f<C>(a: C) where C: P {}
76
+ # }
74
77
  def self.new_list_from_declaration(decl)
78
+ return [] if decl.include?('(')
79
+
75
80
  decl.split(/\s*,\s*/).map { |cons| Constraint.new_declaration(cons) }
76
81
  end
77
82
 
@@ -100,6 +100,7 @@ module Jazzy
100
100
  'typealias' => 'typealias',
101
101
  'associatedtype' => 'associatedtype',
102
102
  'actor' => 'actor',
103
+ 'macro' => 'macro',
103
104
  }.freeze
104
105
 
105
106
  # We treat 'static var' differently to 'class var'
@@ -110,7 +111,7 @@ module Jazzy
110
111
  end
111
112
  return kind unless keywords.member?('static')
112
113
 
113
- kind.gsub(/type/, 'static')
114
+ kind.gsub('type', 'static')
114
115
  end
115
116
 
116
117
  def init_kind(kind, keywords)
@@ -68,7 +68,7 @@ module Jazzy
68
68
 
69
69
  # Parse the symbol files in the given directory
70
70
  def self.parse_symbols(directory)
71
- Dir[directory + '/*.symbols.json'].map do |filename|
71
+ Dir[directory + '/*.symbols.json'].sort.map do |filename|
72
72
  # The @ part is for extensions in our module (before the @)
73
73
  # of types in another module (after the @).
74
74
  File.basename(filename) =~ /(.*?)(@(.*?))?\.symbols/