Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(GH-139) Provide completions for defined types #204

Merged
merged 2 commits into from
Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions lib/puppet-languageserver/manifest/completion_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ module Manifest
module CompletionProvider
def self.complete(content, line_num, char_num, options = {})
options = {
:tasks_mode => false
:tasks_mode => false,
:context => nil # LSP::CompletionContext object
}.merge(options)
items = []
incomplete = false
is_trigger_char = !options[:context].nil? && options[:context].triggerKind == LSP::CompletionTriggerKind::TRIGGERCHARACTER

result = PuppetLanguageServer::PuppetParserHelper.object_under_cursor(content, line_num, char_num,
:multiple_attempts => true,
:disallowed_classes => [Puppet::Pops::Model::QualifiedName, Puppet::Pops::Model::BlockExpression],
:tasks_mode => options[:tasks_mode])
:multiple_attempts => true,
:disallowed_classes => [Puppet::Pops::Model::QualifiedName, Puppet::Pops::Model::BlockExpression],
:tasks_mode => options[:tasks_mode],
:remove_trigger_char => is_trigger_char)
if result.nil?
# We are in the root of the document.

Expand Down Expand Up @@ -41,8 +44,8 @@ def self.complete(content, line_num, char_num, options = {})
# Complete for `$facts[...`
all_facts { |x| items << x } if expr == 'facts'

when 'Puppet::Pops::Model::HostClassDefinition'
# We are in the root of a `class` statement
when 'Puppet::Pops::Model::HostClassDefinition', 'Puppet::Pops::Model::ResourceTypeDefinition'
# We are in the root of a `class` or `define` statement

# Add keywords
keywords(%w[require contain]) { |x| items << x }
Expand Down
3 changes: 2 additions & 1 deletion lib/puppet-languageserver/message_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,11 @@ def request_textdocument_completion(_, json_rpc_message)
line_num = json_rpc_message.params['position']['line']
char_num = json_rpc_message.params['position']['character']
content = documents.document(file_uri)
context = json_rpc_message.params['context'].nil? ? nil : LSP::CompletionContext.new(json_rpc_message.params['context'])

case documents.document_type(file_uri)
when :manifest
return PuppetLanguageServer::Manifest::CompletionProvider.complete(content, line_num, char_num, :tasks_mode => PuppetLanguageServer::DocumentStore.plan_file?(file_uri))
return PuppetLanguageServer::Manifest::CompletionProvider.complete(content, line_num, char_num, :context => context, :tasks_mode => PuppetLanguageServer::DocumentStore.plan_file?(file_uri))
else
raise "Unable to provide completion on #{file_uri}"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def create_ensurable_property

context "Given a simple valid manifest" do
let(:content) { <<-EOT

class Alice {

user { 'Bob':
Expand All @@ -131,14 +132,19 @@ class Alice {
ensure => 'present',
name => 'name',
}

define delta (
) {

}
EOT
}

describe "When inside the root of the manifest" do
let(:char_num) { 0 }
let(:expected_types) { ['keyword','resource_type','function','resource_class'] }

[0, 8].each do |line_num|
[0, 9].each do |line_num|
it "should return a list of keyword, resource_type, function, resource_class regardless of cursor location (Testing line #{line_num})" do
result = subject.complete(content, line_num, char_num)

Expand All @@ -153,26 +159,30 @@ class Alice {
end
end

describe "When inside the root of a class" do
let(:line_num) { 1 }
let(:char_num) { 0 }
let(:expected_types) { ['keyword','resource_type','resource_class'] }
[
{ :name => 'class', :line_num => 1 },
{ :name => 'defined type', :line_num => 19 },
].each do |testcase|
describe "When inside the root of a #{testcase[:name]}" do
let(:char_num) { 0 }
let(:expected_types) { ['keyword','resource_type','resource_class'] }

it 'should return a list of keyword, resource_type, resource_class' do
result = subject.complete(content, line_num, char_num)
it 'should return a list of keyword, resource_type, resource_class' do
result = subject.complete(content, testcase[:line_num], char_num)

result.items.each do |item|
expect(item).to be_completion_item_with_type(expected_types)
end
result.items.each do |item|
expect(item).to be_completion_item_with_type(expected_types)
end

expected_types.each do |typename|
expect(number_of_completion_item_with_type(result,typename)).to be > 0
expected_types.each do |typename|
expect(number_of_completion_item_with_type(result,typename)).to be > 0
end
end
end
end

describe "When inside the root of a resource" do
let(:line_num) { 11 }
let(:line_num) { 12 }
let(:char_num) { 0 }
let(:expected_types) { ['resource_parameter','resource_property'] }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,36 @@
let(:file_uri) { MANIFEST_FILENAME }

it 'should call complete method on the Completion Provider' do
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).with(Object,line_num,char_num,{:tasks_mode=>false}).and_return('something')
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).with(Object, line_num, char_num, { :tasks_mode => false, :context => nil }).and_return('something')
subject.request_textdocument_completion(connection_id, request_message)
end

it 'should set tasks_mode option if the file is Puppet plan file' do
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).with(Object,line_num,char_num,{:tasks_mode=>true}).and_return('something')
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).with(Object, line_num, char_num, { :tasks_mode => true, :context => nil }).and_return('something')
allow(PuppetLanguageServer::DocumentStore).to receive(:plan_file?).and_return true
subject.request_textdocument_completion(connection_id, request_message)
end

context 'with a completion context' do
let(:request_params) {{
'textDocument' => {
'uri' => file_uri
},
'position' => {
'line' => line_num,
'character' => char_num,
},
'context' => {
'triggerKind' => 1
}
}}

it 'should pass the context' do
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).with(Object, line_num, char_num, { :tasks_mode => false, :context => LSP::CompletionContext}).and_return('something')
subject.request_textdocument_completion(connection_id, request_message)
end
end

context 'and an error occurs during completion' do
before(:each) do
expect(PuppetLanguageServer::Manifest::CompletionProvider).to receive(:complete).and_raise('MockError')
Expand Down