Skip to content

Commit

Permalink
(puppetlabsGH-141) Update Sidecar to extract Function V4 API information
Browse files Browse the repository at this point in the history
Previously the Sidecar could only emit information in function V3 API format.
Now that the Sidecar Protocol has been changed to emit V4 information, this
commit updates the Sidecar to extact the V4 information.

This commit:
* Updates the sidecar_protocol_extensions for the Puppet Function object to
  adapt the V3 function information into the V4 version
* Updates the tests for the sidecar_protocol_extensions for the new parameters
  for the V4 API functions
* Updates the Puppet Strings Helper to extract the required information from
  YARN in order to populate the V4 API function metadata.  In particular the
  concepts of function type and arity no longer apply, and have been replaced
  using Function Signatures.
  • Loading branch information
glennsarti committed Jun 10, 2019
1 parent 5dfc8ae commit 8760e60
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
34 changes: 21 additions & 13 deletions lib/puppet-languageserver-sidecar/puppet_strings_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ def populate_functions_from_yard_registry!
obj.calling_source = obj.source
obj.line = item[:line]
obj.doc = item[:docstring][:text]
obj.arity = -1 # We don't care about arity
obj.function_version = item[:type] == 'ruby4x' ? 4 : 3

# Try and determine the function call site from the source file
Expand All @@ -165,20 +164,29 @@ def populate_functions_from_yard_registry!
obj.length = func_name.length + 1
end

case item[:type]
when 'ruby3x'
obj.function_version = 3
# This is a bit hacky but it works (probably). Puppet-Strings doesn't rip this information out, but you do have the
# the source to query
obj.type = item[:source].match(/:rvalue/) ? :rvalue : :statement
when 'ruby4x'
obj.function_version = 4
# All ruby functions are statements
obj.type = :statement
else
PuppetLanguageServerSidecar.log_message(:error, "[#{self.class}] Unknown function type #{item[:type]}")
item[:signatures].each do |signature|
sig = PuppetLanguageServer::Sidecar::Protocol::PuppetFunctionSignature.new

sig.key = signature[:signature]
sig.doc = signature[:docstring][:text]
signature[:docstring][:tags].each do |tag|
case tag[:tag_name]
when 'param'
sig.parameters << {
'name' => tag[:name],
'types' => tag[:types],
'doc' => tag[:text]
}
when 'return'
sig.return_types = tag[:types]
end
end
obj.signatures << sig
end

# TODO: what about {:tag_name=>"since", :text=>"4.0.0"}]}, ? each function
# TODO: what about modifying the docs if it's a V3 func?

@cache[source_path].functions << obj
end
end
Expand Down
21 changes: 17 additions & 4 deletions lib/puppet-languageserver-sidecar/sidecar_protocol_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,23 @@ def self.from_puppet(name, item)
obj.source = item[:source_location][:source]
obj.calling_source = obj.source
obj.line = item[:source_location][:line]
# TODO: name ?
obj.doc = item[:doc]
obj.arity = item[:arity]
obj.type = item[:type]
# This method is only called for V3 API functions. Therefore we need to transform this V3 function into V4 metadata
obj.doc = item[:doc]
obj.function_version = 3
# TODO: Can/Should I reverese engineer arity into parameters? Puppet Strings doesn't e.g.
# result.insertText = "#{data['name']}(${1:value}"
# (2..item_type.arity).each do |index|
# result.insertText += ", ${#{index}:value}"
# end
# result.insertText += ')'
# result.insertTextFormat = LSP::InsertTextFormat::SNIPPET

obj.signatures << PuppetLanguageServer::Sidecar::Protocol::PuppetFunctionSignature.new.from_h!(
'key' => "#{name}()",
'doc' => item[:doc],
'parameters' => [],
'return_types' => ['Any']
)
obj
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,19 @@
describe '.from_puppet' do
it 'should populate from a Puppet function object' do
result = subject_klass.from_puppet(puppet_funcname, puppet_func)
# This method is only called for V3 API functions.
# Therefore we need to assert the V3 function into V4 metadata

expect(result.doc).to eq(puppet_func[:doc])
expect(result.arity).to eq(puppet_func[:arity])
expect(result.type).to eq(puppet_func[:type])
expect(result.function_version).to eq(3)
expect(result.signatures.count).to eq(1)
expect(result.signatures[0].doc).to eq(result.doc)
expect(result.signatures[0].key).to eq("#{puppet_funcname}()")
end
end

describe '#from_json' do
[:doc, :arity, :type].each do |testcase|
[:doc, :function_version, :signatures].each do |testcase|
it "should deserialize a serialized #{testcase} value" do
serial = subject_klass.from_puppet(puppet_funcname, puppet_func)
deserial = subject_klass.new.from_json!(serial.to_json)
Expand Down

0 comments on commit 8760e60

Please sign in to comment.