Skip to content

Commit

Permalink
Identify actors during symbolgraph import
Browse files Browse the repository at this point in the history
  • Loading branch information
johnfairh committed Jun 24, 2021
1 parent 1254d84 commit bff2de6
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 7 deletions.
7 changes: 6 additions & 1 deletion lib/jazzy/symbol_graph/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,13 @@ def rel_source_name(rel, source_node)

# Protocol conformance is redundant if it's unconditional
# and already expressed in the type's declaration.
#
# Skip implementation-detail conformances.
def redundant_conformance?(rel, type, protocol)
type && rel.constraints.empty? && type.conformance?(protocol)
return false unless type

(rel.constraints.empty? && type.conformance?(protocol)) ||
(type.actor? && rel.actor_protocol?)
end

# source is a member/protocol requirement of target
Expand Down
6 changes: 6 additions & 0 deletions lib/jazzy/symbol_graph/relationship.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def default_implementation?
kind == :defaultImplementationOf
end

# Protocol conformances added by compiler to actor decls that
# users aren't interested in.
def actor_protocol?
%w[Actor Sendable].include?(target_fallback)
end

def initialize(hash)
kind = hash[:kind]
unless KINDS.include?(kind)
Expand Down
4 changes: 4 additions & 0 deletions lib/jazzy/symbol_graph/sym_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def protocol?
symbol.kind.end_with?('protocol')
end

def actor?
symbol.kind.end_with?('actor')
end

def constraints
symbol.constraints
end
Expand Down
27 changes: 21 additions & 6 deletions lib/jazzy/symbol_graph/symbol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def name
def initialize(hash)
self.usr = hash[:identifier][:precise]
self.path_components = hash[:pathComponents]
raw_decl = hash[:declarationFragments].map { |f| f[:spelling] }.join
init_kind(hash[:kind][:identifier])
raw_decl, keywords = parse_decl_fragments(hash[:declarationFragments])
init_kind(hash[:kind][:identifier], keywords)
init_declaration(raw_decl)
if func_signature = hash[:functionSignature]
init_func_signature(func_signature)
Expand All @@ -40,6 +40,16 @@ def initialize(hash)
init_generic_type_params(hash)
end

def parse_decl_fragments(fragments)
decl = ''
keywords = Set.new
fragments.each do |frag|
decl += frag[:spelling]
keywords.add(frag[:spelling]) if frag[:kind] == 'keyword'
end
[decl, keywords]
end

# Repair problems with SymbolGraph's declprinter

def init_declaration(raw_decl)
Expand Down Expand Up @@ -85,16 +95,21 @@ def init_func_signature(func_signature)
'static.subscript' => 'function.subscript',
'typealias' => 'typealias',
'associatedtype' => 'associatedtype',
'actor' => 'actor',
}.freeze

# We treat 'static var' differently to 'class var'
def adjust_kind_for_declaration(kind)
return kind unless declaration =~ /\bstatic\b/
# We treat actors as first-class entities
def adjust_kind_for_declaration(kind, keywords)
if kind == 'swift.class' && keywords.member?('actor')
return 'swift.actor'
end
return kind unless keywords.member?('static')
kind.gsub(/type/, 'static')
end

def init_kind(kind)
adjusted = adjust_kind_for_declaration(kind)
def init_kind(kind, keywords)
adjusted = adjust_kind_for_declaration(kind, keywords)
sourcekit_kind = KIND_MAP[adjusted.sub('swift.', '')]
raise "Unknown symbol kind '#{kind}'" unless sourcekit_kind
self.kind = 'source.lang.swift.decl.' + sourcekit_kind
Expand Down

0 comments on commit bff2de6

Please sign in to comment.