Skip to content

(GH-269) Fix Workspace Symbol Provider #271

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

Merged
merged 5 commits into from
Jul 17, 2020
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
18 changes: 16 additions & 2 deletions lib/puppet-languageserver/manifest/document_symbol_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def self.workspace_symbols(query, object_cache)
'kind' => LSP::SymbolKind::METHOD,
'location' => {
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
# Don't have char pos for functions so just pick extreme values
# Don't have char pos for types so just pick extreme values
'range' => LSP.create_range(item.line, 0, item.line, 1024)
}
)
Expand All @@ -38,11 +38,25 @@ def self.workspace_symbols(query, object_cache)
'kind' => LSP::SymbolKind::CLASS,
'location' => {
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
# Don't have char pos for functions so just pick extreme values
# Don't have char pos for classes so just pick extreme values
'range' => LSP.create_range(item.line, 0, item.line, 1024)
}
)

when PuppetLanguageServer::Sidecar::Protocol::PuppetDataType
result << LSP::SymbolInformation.new(
'name' => key_string,
'kind' => LSP::SymbolKind::NAMESPACE,
'location' => {
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
# Don't have char pos for data types so just pick extreme values
'range' => LSP.create_range(item.line, 0, item.line, 1024)
}
)

when PuppetLanguageServer::Sidecar::Protocol::Fact
# Do nothing

else
PuppetLanguageServer.log_message(:warn, "[Manifest::DocumentSymbolProvider] Unknown object type #{item.class}")
end
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet-languageserver/message_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def workspace_root_from_initialize_params(params)
# We don't support multiple workspace folders yet, so just select the first one
return UriHelper.uri_path(params['workspaceFolders'][0]['uri'])
end
return UriHelper.uri_path(params['rootUri']) if params.key?('rootUri')
return UriHelper.uri_path(params['rootUri']) if params.key?('rootUri') && !params['rootUri'].nil?
params['rootPath']
end
end
Expand Down
9 changes: 6 additions & 3 deletions lib/puppet-languageserver/uri_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
module PuppetLanguageServer
module UriHelper
def self.build_file_uri(path)
'file://' + Puppet::Util.uri_encode(path.start_with?('/') ? path : '/' + path)
if path.nil?
nil
else
'file://' + Puppet::Util.uri_encode(path.start_with?('/') ? path : '/' + path)
end
end

def self.uri_path(uri_string)
return nil if uri_string.nil?
Puppet::Util.uri_to_path(URI(uri_string))
uri_string.nil? ? nil : Puppet::Util.uri_to_path(URI(uri_string))
end

# Compares two URIs and returns the relative path
Expand Down
6 changes: 5 additions & 1 deletion lib/puppet_editor_services/protocol/json_rpc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def receive_json_message_as_string(content)
def receive_json_message_as_hash(json_obj)
# There's no need to convert it to an object quite yet
# Need to validate that this is indeed a valid message
id = json_obj[KEY_ID]
unless json_obj[KEY_JSONRPC] == JSONRPC_VERSION
PuppetEditorServices.log_message(:error, 'Invalid JSON RPC version')
reply_error id, CODE_INVALID_REQUEST, MSG_INVALID_REQ_JSONRPC
Expand All @@ -159,7 +160,6 @@ def receive_json_message_as_hash(json_obj)
end
end

id = json_obj[KEY_ID]
# Requests and Responses must have an ID that is either a string or integer
if is_request || is_response
unless id.is_a?(String) || id.is_a?(Integer)
Expand Down Expand Up @@ -197,6 +197,10 @@ def receive_json_message_as_hash(json_obj)
false
end

def reply_error(id, code, message)
send_json_string ::PuppetEditorServices::Protocol::JsonRPCMessages.reply_error_by_id(id, code, message).to_json
end

# region Server-to-Client request/response methods
def send_client_request(rpc_method, params)
request = ::PuppetEditorServices::Protocol::JsonRPCMessages.new_request(client_request_id!, rpc_method, params)
Expand Down
6 changes: 5 additions & 1 deletion lib/puppet_editor_services/protocol/json_rpc_messages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,14 @@ def self.reply_result(request, result)
end

def self.reply_error(request, code, message)
reply_error_by_id(request.id, code, message)
end

def self.reply_error_by_id(id, code, message)
# Note - Strictly speaking the error should be typed object, however as this hidden behind
# this method it's easier to just pass in a known hash construct
ResponseMessage.new.from_h!(
'id' => request.id,
'id' => id,
'error' => {
'code' => code,
'message' => message
Expand Down
23 changes: 18 additions & 5 deletions spec/languageserver/acceptance/end_to_end_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# Format range | X | - | - |
# OnType Formatting | X | - | - |
# Document Symbols | X | - | - |
# Workspace Symbols | - | | |
# Workspace Symbols | - | | X |

describe 'End to End Testing' do
before(:each) do
Expand Down Expand Up @@ -321,10 +321,23 @@ def path_to_uri(path)
@client.send_data(@client.puppetfile_getdependencies_request(@client.next_seq_id, puppetfile_uri))
expect(@client).to receive_message_with_request_id_within_timeout([@client.current_seq_id, 10])
result = @client.data_from_request_seq_id(@client.current_seq_id)
# Expect something to be returned
expect(result['result']).not_to be_nil
expect(result['result']['dependencies']).not_to be_nil
expect(result['result']['dependencies']).not_to be_empty
# Expect something to be returned
expect(result['result']).not_to be_nil
expect(result['result']['dependencies']).not_to be_nil
expect(result['result']['dependencies']).not_to be_empty

# Workspace Symbols
@client.send_data(@client.workspace_symbols_request(@client.next_seq_id, ''))
expect(@client).to receive_message_with_request_id_within_timeout([@client.current_seq_id, 15])
result = @client.data_from_request_seq_id(@client.current_seq_id)
# Expect something to be returned
expect(result['result']).not_to be_nil
# Should contain the default puppet user class
index = result['result'].find { |item| item['name'] == 'user' && item['kind'] == 6 }
expect(index).not_to be_nil
# Should contain a profile from the control-repo
index = result['result'].find { |item| item['name'] == 'profile::editorservices' && item['kind'] == 5 }
expect(index).not_to be_nil

# Start shutdown process
@client.clear_messages!
Expand Down
Loading