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
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 16 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
13 14 15 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 13 def ext_nodes @ext_nodes end |
#module_name ⇒ Object
Returns the value of attribute module_name.
10 11 12 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 10 def module_name @module_name end |
#relationships ⇒ Object
- Relationship
12 13 14 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 12 def relationships @relationships end |
#symbol_nodes ⇒ Object
usr -> SymNode
11 12 13 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 11 def symbol_nodes @symbol_nodes end |
Instance Method Details
#add_ext_conformance(type_usr, type_name, protocol, constraints) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 49 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
39 40 41 42 43 44 45 46 47 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 39 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
35 36 37 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 35 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
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 101 def rebuild_conformance(rel, source, target) protocol_name = rel_target_name(rel, target) return if redundant_conformance?(rel, source, protocol_name) type_constraints = 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”
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 119 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”
141 142 143 144 145 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 141 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
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 86 def rebuild_member(rel, source, target) return unless source source.protocol_requirement = rel.protocol_requirement? constraints = ExtConstraints.new(target&.constraints, source.unique_context_constraints(target)) # Add to its parent or invent an extension unless 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
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 148 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.
81 82 83 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 81 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
74 75 76 77 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 74 def rel_source_name(rel, 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
67 68 69 70 71 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 67 def rel_target_name(rel, 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
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/jazzy/symbol_graph/graph.rb', line 170 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 |