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.

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.



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

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.



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

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.



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

def protocol_requirement=(value)
  @protocol_requirement = value
end

#superclass_nameObject

Returns the value of attribute superclass_name.



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

def superclass_name
  @superclass_name
end

#symbolObject

Returns the value of attribute symbol.



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

def symbol
  @symbol
end

#unlisted=(value) ⇒ Object (writeonly)

Sets the attribute unlisted

Parameters:

  • value

    the value to set the attribute unlisted to.



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

def unlisted=(value)
  @unlisted = value
end

Instance Method Details

#<=>(other) ⇒ Object



158
159
160
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 158

def <=>(other)
  symbol <=> other.symbol
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)


97
98
99
100
101
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 97

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

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

#constraintsObject



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

def constraints
  symbol.constraints
end

#full_declarationObject



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

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

#inherits_clauseObject



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

def inherits_clause
  return '' unless superclass_name

  " : #{superclass_name}"
end

#override?Boolean

Returns:

  • (Boolean)


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

def override?
  @override
end

#parent_qualified_nameObject



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

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

#protocol?Boolean

Returns:

  • (Boolean)


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

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

#protocol_requirement?Boolean

Returns:

  • (Boolean)


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

def protocol_requirement?
  @protocol_requirement
end

#qualified_nameObject



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

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

#to_sourcekitObject

rubocop:disable Metrics/MethodLength



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 122

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,
  }
  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
end

#top_level_decl?Boolean

Returns:

  • (Boolean)


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

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


72
73
74
75
76
77
78
79
80
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 72

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.



85
86
87
88
89
90
91
92
93
# File 'lib/jazzy/symbol_graph/sym_node.rb', line 85

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



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

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