Class: Jazzy::SymbolGraph::SymNode

Inherits:
BaseNode
  • Object
show all
Includes:
Comparable
Defined in:
lib/jazzy/symbol_graph/sym_node.rb

Overview

A SymNode is a node of the reconstructed syntax tree holding a symbol. It can turn itself into SourceKit and helps decode extensions. rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Attributes inherited from BaseNode

#children, #parent

Instance Method Summary collapse

Methods inherited from BaseNode

#add_child, #children_to_sourcekit

Constructor Details

#initialize(symbol) ⇒ SymNode

Returns a new instance of SymNode.



48
49
50
51
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 48

def initialize(symbol)
  self.symbol = symbol
  super()
end

Instance Attribute Details

#override=(value) ⇒ Object (writeonly)

Sets the attribute override

Parameters:

  • value

    the value to set the attribute override to.



31
32
33
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 31

def override=(value)
  @override = value
end

#protocol_requirement=(value) ⇒ Object (writeonly)

Sets the attribute protocol_requirement

Parameters:

  • value

    the value to set the attribute protocol_requirement to.



32
33
34
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 32

def protocol_requirement=(value)
  @protocol_requirement = value
end

#superclass_nameObject

Returns the value of attribute superclass_name.



34
35
36
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 34

def superclass_name
  @superclass_name
end

#symbolObject

Returns the value of attribute symbol.



30
31
32
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 30

def symbol
  @symbol
end

#unlisted=(value) ⇒ Object (writeonly)

Sets the attribute unlisted

Parameters:

  • value

    the value to set the attribute unlisted to.



33
34
35
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 33

def unlisted=(value)
  @unlisted = value
end

Instance Method Details

#<=>(other) ⇒ Object



170
171
172
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 170

def <=>(other)
  symbol <=> other.symbol
end

#actor?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 65

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

#async?Boolean

approximately…

Returns:

  • (Boolean)


121
122
123
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 121

def async?
  symbol.declaration =~ /\basync\b[^)]*$/
end

#conformance?(protocol) ⇒ Boolean

Messy check whether we need to fabricate an extension for a protocol conformance: don’t bother if it’s already in the type declaration.

Returns:

  • (Boolean)


102
103
104
105
106
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 102

def conformance?(protocol)
  return false unless symbol.declaration =~ /(?<=:).*?(?=(where|$))/

  Regexp.last_match[0] =~ /\b#{protocol}\b/
end

#constraintsObject



69
70
71
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 69

def constraints
  symbol.constraints
end

#full_declarationObject



125
126
127
128
129
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 125

def full_declaration
  symbol.attributes
    .append(symbol.declaration + inherits_clause + where_clause)
    .join("\n")
end

#inherits_clauseObject



114
115
116
117
118
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 114

def inherits_clause
  return '' unless superclass_name

  " : #{superclass_name}"
end

#override?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 36

def override?
  @override
end

#parent_qualified_nameObject



57
58
59
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 57

def parent_qualified_name
  symbol.path_components[0...-1].join('.')
end

#protocol?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 61

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

#protocol_requirement?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 40

def protocol_requirement?
  @protocol_requirement
end

#qualified_nameObject



53
54
55
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 53

def qualified_name
  symbol.path_components.join('.')
end

#to_sourcekitObject

rubocop:disable Metrics/MethodLength



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 132

def to_sourcekit
  declaration = full_declaration
  xml_declaration = "<swift>#{CGI.escapeHTML(declaration)}</swift>"

  hash = {
    'key.kind' => symbol.kind,
    'key.usr' => symbol.usr,
    'key.name' => symbol.name,
    'key.accessibility' => symbol.acl,
    'key.parsed_decl' => declaration,
    'key.annotated_decl' => xml_declaration,
    'key.symgraph_async' => async?,
  }
  if docs = symbol.doc_comments
    hash['key.doc.comment'] = docs
    hash['key.doc.full_as_xml'] = ''
  end
  if params = symbol.parameter_names
    hash['key.doc.parameters'] =
      params.map { |name| { 'name' => name } }
  end
  if location = symbol.location
    hash['key.filepath'] = location[:filename]
    hash['key.doc.line'] = location[:line] + 1
    hash['key.doc.column'] = location[:character] + 1
  end
  unless children.empty?
    hash['key.substructure'] = children_to_sourcekit
  end
  hash['key.symgraph_spi'] = true if symbol.spi

  hash
end

#top_level_decl?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 44

def top_level_decl?
  !@unlisted && parent.nil?
end

#try_add_child(node, unique_context_constraints) ⇒ Object

Add another SymNode as a member if possible. It must go in an extension if either:

- it has different generic constraints to us; or
- we're a protocol and it's a default impl / ext method


77
78
79
80
81
82
83
84
85
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 77

def try_add_child(node, unique_context_constraints)
  unless unique_context_constraints.empty? &&
         (!protocol? || node.protocol_requirement?)
    return false
  end

  add_child(node)
  true
end

#unique_context_constraints(context) ⇒ Object

The ‘Constraint`s on this decl that are both:

  1. Unique, ie. not just inherited from its context; and

  2. Constraining the *context’s* gen params rather than our own.



90
91
92
93
94
95
96
97
98
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 90

def unique_context_constraints(context)
  return symbol.constraints unless context

  new_generic_type_params =
    symbol.generic_type_params - context.symbol.generic_type_params

  (symbol.constraints - context.symbol.constraints)
    .select { |con| con.type_names.disjoint?(new_generic_type_params) }
end

#where_clauseObject

Generate the ‘where’ clause for the declaration



109
110
111
112
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 109

def where_clause
  parent_constraints = parent&.constraints || []
  (constraints - parent_constraints).to_where_clause
end