Module: PuppetLanguageServer::Manifest::HoverProvider

Defined in:
lib/puppet-languageserver/manifest/hover_provider.rb

Class Method Summary collapse

Class Method Details

.get_attribute_class_parameter_content(item_class, param) ⇒ Object



147
148
149
150
151
152
153
154
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 147

def self.get_attribute_class_parameter_content(item_class, param)
  param_type = item_class.parameters[param]
  return nil if param_type.nil?

  content = "**#{param}** Parameter"
  content += "\n\n#{param_type[:doc]}" unless param_type[:doc].nil?
  content
end

.get_attribute_type_parameter_content(item_type, param) ⇒ Object



132
133
134
135
136
137
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 132

def self.get_attribute_type_parameter_content(item_type, param)
  param_type = item_type.attributes[param]
  content = "**#{param}** Parameter"
  content += "\n\n#{param_type[:doc]}" unless param_type[:doc].nil?
  content
end

.get_attribute_type_property_content(item_type, property) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 139

def self.get_attribute_type_property_content(item_type, property)
  prop_type = item_type.attributes[property]
  content = "**#{property}** Property"
  content += "\n\n(_required_)" if prop_type[:required?]
  content += "\n\n#{prop_type[:doc]}" unless prop_type[:doc].nil?
  content
end

.get_call_named_function_expression_content(session_state, item, tasks_mode) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 156

def self.get_call_named_function_expression_content(session_state, item, tasks_mode)
  func_name = item.functor_expr.value

  func_info = PuppetLanguageServer::PuppetHelper.function(session_state, func_name, tasks_mode)
  raise "Function #{func_name} does not exist" if func_info.nil?

  content = "**#{func_name}** Function"
  content += "\n\n#{func_info.doc}" unless func_info.doc.nil?

  content
end

.get_fact_content(session_state, factname) ⇒ Object

Content generation functions



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 116

def self.get_fact_content(session_state, factname)
  fact = PuppetLanguageServer::FacterHelper.fact(session_state, factname)
  return nil if fact.nil?

  value = fact.value
  content = "**#{factname}** Fact\n\n"

  if value.is_a?(Hash)
    content = "#{content}```\n#{JSON.pretty_generate(value)}\n```"
  else
    content += value.to_s
  end

  content
end

.get_hover_content_for_access_expression(session_state, path, expr) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 87

def self.get_hover_content_for_access_expression(session_state, path, expr)
  if expr == 'facts'
    # We are dealing with the facts variable
    # Just get the first part of the array and display that
    fact_array = path[-1]
    if fact_array.respond_to? :eContents
      fact_array_content = fact_array.eContents
    else
      fact_array_content = []
      fact_array._pcore_contents { |item| fact_array_content.push item }
    end

    if fact_array_content.length > 1
      factname = fact_array_content[1].value
      content = get_fact_content(session_state, factname)
    end
  elsif expr.start_with?('::') && expr.rindex(':') == 1
    # We are dealing with a top local scope variable - Possible fact name
    factname = expr.slice(2, expr.length - 2)
    content = get_fact_content(session_state, factname)
  else
    # Could be a flatout fact name.  May not *shrugs*.  That method of access is deprecated
    content = get_fact_content(session_state, expr)
  end

  content
end

.get_resource_expression_content(session_state, item) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 168

def self.get_resource_expression_content(session_state, item)
  name = item.type_name.value
  # Strip top scope colons if found
  name = name[2..-1] if name.start_with?('::')
  # Get an instance of the type
  item_object = PuppetLanguageServer::PuppetHelper.get_type(session_state, name)
  return get_puppet_type_content(item_object) unless item_object.nil?

  item_object = PuppetLanguageServer::PuppetHelper.get_class(session_state, name)
  return get_puppet_class_content(item_object) unless item_object.nil?

  raise "#{name} is not a valid puppet type"
end

.resolve(session_state, content, line_num, char_num, options = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/puppet-languageserver/manifest/hover_provider.rb', line 6

def self.resolve(session_state, content, line_num, char_num, options = {})
  options = {
    tasks_mode: false
  }.merge(options)
  result = PuppetLanguageServer::PuppetParserHelper.object_under_cursor(content, line_num, char_num,
                                                                        disallowed_classes: [Puppet::Pops::Model::BlockExpression],
                                                                        tasks_mode: options[:tasks_mode])
  return nil if result.nil?

  path = result[:path]
  item = result[:model]

  # Munge the item
  # We're not really interested in the Name of thing yet, we want the "thing" it's a name of
  item = path.pop if item.instance_of?(Puppet::Pops::Model::QualifiedName) && !path.empty?

  content = nil
  case item.class.to_s
  when 'Puppet::Pops::Model::ResourceExpression'
    content = get_resource_expression_content(session_state, item)
  when 'Puppet::Pops::Model::LiteralString'
    if path[-1].instance_of?(Puppet::Pops::Model::AccessExpression)
      expr = path[-1].left_expr.expr.value

      content = get_hover_content_for_access_expression(session_state, path, expr)
    elsif path[-1].instance_of?(Puppet::Pops::Model::ResourceBody)
      # We are hovering over the resource name
      content = get_resource_expression_content(session_state, path[-2])
    end
  when 'Puppet::Pops::Model::VariableExpression'
    expr = item.expr.value

    content = get_hover_content_for_access_expression(session_state, path, expr)
  when 'Puppet::Pops::Model::CallNamedFunctionExpression'
    content = get_call_named_function_expression_content(session_state, item, options[:tasks_mode])
  when 'Puppet::Pops::Model::AttributeOperation'
    # Get the parent resource class
    distance_up_ast = -1
    parent_klass = path[distance_up_ast]
    while !parent_klass.nil? && parent_klass.class.to_s != 'Puppet::Pops::Model::ResourceBody'
      distance_up_ast -= 1
      parent_klass = path[distance_up_ast]
    end
    raise "Unable to find suitable parent object for object of type #{item.class}" if parent_klass.nil?

    resource_type_name = path[distance_up_ast - 1].type_name.value
    # Check if it's a Puppet Type
    resource_object = PuppetLanguageServer::PuppetHelper.get_type(session_state, resource_type_name)
    unless resource_object.nil?
      # Check if it's a property
      attribute = resource_object.attributes[item.attribute_name.intern]
      case attribute[:type]
      when :property
        content = get_attribute_type_property_content(resource_object, item.attribute_name.intern)
      when :param
        content = get_attribute_type_parameter_content(resource_object, item.attribute_name.intern)
      end
    end
    # Check if it's a Puppet Class / Defined Type
    if resource_object.nil?
      resource_object = PuppetLanguageServer::PuppetHelper.get_class(session_state, resource_type_name)
      content = get_attribute_class_parameter_content(resource_object, item.attribute_name) unless resource_object.nil?
    end
    raise "#{resource_type_name} is not a valid puppet type, class or defined type" if resource_object.nil?
  when 'Puppet::Pops::Model::QualifiedReference'
    # https://github.com/puppetlabs/puppet-specifications/blob/master/language/names.md#names
    # Datatypes have to start with uppercase and can be fully qualified
    if /^[A-Z][a-zA-Z:0-9]*$/.match?(item.cased_value) # rubocop:disable Style/GuardClause
      content = get_puppet_datatype_content(session_state, item, options[:tasks_mode])
    else
      raise "#{item.cased_value} is an unknown QualifiedReference"
    end
  else
    raise "Unable to generate Hover information for object of type #{item.class}"
  end

  return nil if content.nil?

  LSP::Hover.new('contents' => content)
end