Class: Jazzy::SymbolGraph::Graph
- Inherits:
-
Object
- Object
- Jazzy::SymbolGraph::Graph
- Defined in:
- lib/jazzy/symbol_graph/graph.rb
Overview
A Graph is the coordinator to import a symbolgraph json file. Deserialize it to Symbols and Relationships, then rebuild the AST shape using SymNodes and ExtNodes and extract SourceKit json.
Instance Attribute Summary collapse
-
#ext_nodes ⇒ Object
(usr, constraints) -> ExtNode.
-
#module_name ⇒ Object
Returns the value of attribute module_name.
-
#relationships ⇒ Object
[Relationship].
-
#symbol_nodes ⇒ Object
usr -> SymNode.
Instance Method Summary collapse
- #add_ext_conformance(type_usr, type_name, protocol, constraints) ⇒ Object
- #add_ext_member(type_usr, member_node, constraints) ⇒ Object
-
#ext_key(usr, constraints) ⇒ Object
ExtNode index.
-
#initialize(json, module_name) ⇒ Graph
constructor
Parse the JSON into flat tables of data.
-
#rebuild_conformance(rel, source, target) ⇒ Object
“source : target” either from type decl or ext decl.
-
#rebuild_default_implementation(_rel, source, target) ⇒ Object
“source is a default implementation of protocol requirement target”.
-
#rebuild_inherits(_rel, source, target) ⇒ Object
“source is a class that inherits from target”.
-
#rebuild_member(rel, source, target) ⇒ Object
source is a member/protocol requirement of target.
-
#rebuild_rel(rel) ⇒ Object
Process a structural relationship to link nodes.
-
#redundant_conformance?(rel, type, protocol) ⇒ Boolean
Protocol conformance is redundant if it’s unconditional and already expressed in the type’s declaration.
-
#rel_source_name(rel, source_node) ⇒ Object
Same for the source end.
-
#rel_target_name(rel, target_node) ⇒ Object
Increasingly desparate ways to find the name of the symbol at the target end of a relationship.
-
#to_sourcekit ⇒ Object
Rebuild the AST structure and convert to SourceKit.
Constructor Details
#initialize(json, module_name) ⇒ Graph
Parse the JSON into flat tables of data
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 14 def initialize(json, module_name) self.module_name = module_name graph = JSON.parse(json, symbolize_names: true) self.symbol_nodes = {} graph[:symbols].each do |hash| symbol = Symbol.new(hash) symbol_nodes[symbol.usr] = SymNode.new(symbol) end self.relationships = graph[:relationships].map { |hash| Relationship.new(hash) } self.ext_nodes = {} end |
Instance Attribute Details
#ext_nodes ⇒ Object
(usr, constraints) -> ExtNode
11 12 13 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 11 def ext_nodes @ext_nodes end |
#module_name ⇒ Object
Returns the value of attribute module_name.
8 9 10 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 8 def module_name @module_name end |
#relationships ⇒ Object
- Relationship
10 11 12 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 10 def relationships @relationships end |
#symbol_nodes ⇒ Object
usr -> SymNode
9 10 11 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 9 def symbol_nodes @symbol_nodes end |
Instance Method Details
#add_ext_conformance(type_usr, type_name, protocol, constraints) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 47 def add_ext_conformance(type_usr, type_name, protocol, constraints) key = ext_key(type_usr, constraints.ext) if ext_node = ext_nodes[key] ext_node.add_conformance(protocol) else ext_nodes[key] = ExtNode.new_for_conformance(type_usr, type_name, protocol, constraints) end end |
#add_ext_member(type_usr, member_node, constraints) ⇒ Object
37 38 39 40 41 42 43 44 45 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 37 def add_ext_member(type_usr, member_node, constraints) key = ext_key(type_usr, constraints.ext) if ext_node = ext_nodes[key] ext_node.add_child(member_node) else ext_nodes[key] = ExtNode.new_for_member(type_usr, member_node, constraints) end end |
#ext_key(usr, constraints) ⇒ Object
ExtNode index. (type USR, extension constraints) -> ExtNode. This minimizes the number of extensions
33 34 35 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 33 def ext_key(usr, constraints) usr + constraints.map(&:to_swift).join end |
#rebuild_conformance(rel, source, target) ⇒ Object
“source : target” either from type decl or ext decl
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 99 def rebuild_conformance(rel, source, target) protocol_name = rel_target_name(rel, target) return if redundant_conformance?(rel, source, protocol_name) type_constraints = (source && source.constraints) || [] constraints = ExtConstraints.new(type_constraints, rel.constraints - type_constraints) # Create an extension or enhance an existing one add_ext_conformance(rel.source_usr, rel_source_name(rel, source), protocol_name, constraints) end |
#rebuild_default_implementation(_rel, source, target) ⇒ Object
“source is a default implementation of protocol requirement target”
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 117 def rebuild_default_implementation(_rel, source, target) return unless source unless target && (target_parent = target.parent) && target_parent.is_a?(SymNode) # Could probably figure this out with demangle, but... warn "Can't resolve membership of default implementation "\ "#{source.symbol.usr}." source.unlisted = true return end constraints = ExtConstraints.new(target_parent.constraints, source.unique_context_constraints(target_parent)) add_ext_member(target_parent.symbol.usr, source, constraints) end |
#rebuild_inherits(_rel, source, target) ⇒ Object
“source is a class that inherits from target”
139 140 141 142 143 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 139 def rebuild_inherits(_rel, source, target) if source && target source.superclass_name = target.symbol.name end end |
#rebuild_member(rel, source, target) ⇒ Object
source is a member/protocol requirement of target
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 84 def rebuild_member(rel, source, target) return unless source source.protocol_requirement = rel.protocol_requirement? constraints = ExtConstraints.new(target && target.constraints, source.unique_context_constraints(target)) # Add to its parent or invent an extension unless target && target.try_add_child(source, constraints.ext) add_ext_member(rel.target_usr, source, constraints) end end |
#rebuild_rel(rel) ⇒ Object
Process a structural relationship to link nodes
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 146 def rebuild_rel(rel) source = symbol_nodes[rel.source_usr] target = symbol_nodes[rel.target_usr] case rel.kind when :memberOf, :optionalRequirementOf, :requirementOf rebuild_member(rel, source, target) when :conformsTo rebuild_conformance(rel, source, target) when :defaultImplementationOf rebuild_default_implementation(rel, source, target) when :inheritsFrom rebuild_inherits(rel, source, target) end # don't seem to care about: # - overrides: not bothered, also unimplemented for protocols end |
#redundant_conformance?(rel, type, protocol) ⇒ Boolean
Protocol conformance is redundant if it’s unconditional and already expressed in the type’s declaration.
79 80 81 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 79 def redundant_conformance?(rel, type, protocol) type && rel.constraints.empty? && type.conformance?(protocol) end |
#rel_source_name(rel, source_node) ⇒ Object
Same for the source end. Less help from the tool here
72 73 74 75 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 72 def rel_source_name(rel, source_node) (source_node && source_node.qualified_name) || Jazzy::SymbolGraph.demangle(rel.source_usr) end |
#rel_target_name(rel, target_node) ⇒ Object
Increasingly desparate ways to find the name of the symbol at the target end of a relationship
65 66 67 68 69 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 65 def rel_target_name(rel, target_node) (target_node && target_node.symbol.name) || rel.target_fallback || Jazzy::SymbolGraph.demangle(rel.target_usr) end |
#to_sourcekit ⇒ Object
Rebuild the AST structure and convert to SourceKit
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 168 def to_sourcekit # Do default impls after the others so we can find protocol # type nodes from protocol requirements. default_impls, other_rels = relationships.partition(&:default_implementation?) (other_rels + default_impls).each { |r| rebuild_rel(r) } root_symbol_nodes = symbol_nodes.values .select(&:top_level_decl?) .sort .map(&:to_sourcekit) root_ext_nodes = ext_nodes.values .sort .map { |n| n.to_sourcekit(module_name) } { 'key.diagnostic_stage' => 'parse', 'key.substructure' => root_symbol_nodes + root_ext_nodes, } end |