Skip to content

Commit e33bc39

Browse files
committed
(GH-88) Add a workspace symbol provider
The object cache contains all of the type, function and class information so it should be easily be able to be queried and then emit these results as part of a workspace symbol request (as opposed to document symbol). This commit adds the provider and cache methods to support querying all objects in the cache.
1 parent 4d7d1eb commit e33bc39

File tree

6 files changed

+140
-5
lines changed

6 files changed

+140
-5
lines changed

lib/languageserver/document_symbol.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,62 @@ def self.create(options)
7676
result
7777
end
7878
end
79+
80+
# /**
81+
# * Represents information about programming constructs like variables, classes,
82+
# * interfaces etc.
83+
# */
84+
# interface SymbolInformation {
85+
# /**
86+
# * The name of this symbol.
87+
# */
88+
# name: string;
89+
90+
# /**
91+
# * The kind of this symbol.
92+
# */
93+
# kind: number;
94+
95+
# /**
96+
# * Indicates if this symbol is deprecated.
97+
# */
98+
# deprecated?: boolean;
99+
100+
# /**
101+
# * The location of this symbol. The location's range is used by a tool
102+
# * to reveal the location in the editor. If the symbol is selected in the
103+
# * tool the range's start information is used to position the cursor. So
104+
# * the range usually spans more then the actual symbol's name and does
105+
# * normally include things like visibility modifiers.
106+
# *
107+
# * The range doesn't have to denote a node range in the sense of a abstract
108+
# * syntax tree. It can therefore not be used to re-construct a hierarchy of
109+
# * the symbols.
110+
# */
111+
# location: Location;
112+
113+
# /**
114+
# * The name of the symbol containing this symbol. This information is for
115+
# * user interface purposes (e.g. to render a qualifier in the user interface
116+
# * if necessary). It can't be used to re-infer a hierarchy for the document
117+
# * symbols.
118+
# */
119+
# containerName?: string;
120+
# }
121+
module SymbolInformation
122+
def self.create(options)
123+
result = {}
124+
raise('name is a required field for SymbolInformation') if options['name'].nil?
125+
raise('kind is a required field for SymbolInformation') if options['kind'].nil?
126+
raise('location is a required field for DocumentSymbol') if options['location'].nil?
127+
128+
result['name'] = options['name']
129+
result['kind'] = options['kind']
130+
result['deprecated'] = options['deprecated'] unless options['deprecated'].nil?
131+
result['location'] = options['location']
132+
result['containerName'] = options['containerName'] unless options['containerName'].nil?
133+
134+
result
135+
end
136+
end
79137
end

lib/puppet-languageserver/manifest/document_symbol_provider.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,56 @@
11
module PuppetLanguageServer
22
module Manifest
33
module DocumentSymbolProvider
4+
def self.workspace_symbols(query)
5+
query = '' if query.nil?
6+
result = []
7+
PuppetLanguageServer::PuppetHelper.all_objects do |key, item|
8+
key_string = key.to_s
9+
next unless key_string.include?(query)
10+
case item
11+
when PuppetLanguageServer::PuppetHelper::PuppetType
12+
result << LanguageServer::SymbolInformation.create(
13+
'name' => key_string,
14+
'kind' => LanguageServer::SYMBOLKIND_METHOD,
15+
'location' => LanguageServer::Location.create(
16+
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
17+
'fromline' => item.line,
18+
'fromchar' => 0, # Don't have char pos for types
19+
'toline' => item.line,
20+
'tochar' => 1024, # Don't have char pos for types
21+
)
22+
)
23+
24+
when PuppetLanguageServer::PuppetHelper::PuppetFunction
25+
result << LanguageServer::SymbolInformation.create(
26+
'name' => key_string,
27+
'kind' => LanguageServer::SYMBOLKIND_FUNCTION,
28+
'location' => LanguageServer::Location.create(
29+
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
30+
'fromline' => item.line,
31+
'fromchar' => 0, # Don't have char pos for functions
32+
'toline' => item.line,
33+
'tochar' => 1024, # Don't have char pos for functions
34+
)
35+
)
36+
37+
when PuppetLanguageServer::PuppetHelper::PuppetClass
38+
result << LanguageServer::SymbolInformation.create(
39+
'name' => key_string,
40+
'kind' => LanguageServer::SYMBOLKIND_CLASS,
41+
'location' => LanguageServer::Location.create(
42+
'uri' => PuppetLanguageServer::UriHelper.build_file_uri(item.source),
43+
'fromline' => item.line,
44+
'fromchar' => 0, # Don't have char pos for classes
45+
'toline' => item.line,
46+
'tochar' => 1024, # Don't have char pos for classes
47+
)
48+
)
49+
end
50+
end
51+
result
52+
end
53+
454
def self.extract_document_symbols(content)
555
parser = Puppet::Pops::Parser::Parser.new
656
result = parser.parse_string(content, '')

lib/puppet-languageserver/message_router.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ def receive_request(request)
164164
PuppetLanguageServer.log_message(:error, "(textDocument/documentSymbol) #{exception}")
165165
request.reply_result(nil)
166166
end
167+
168+
when 'workspace/symbol'
169+
begin
170+
result = []
171+
result.concat(PuppetLanguageServer::Manifest::DocumentSymbolProvider.workspace_symbols(request.params['query']))
172+
request.reply_result(result)
173+
rescue StandardError => exception
174+
PuppetLanguageServer.log_message(:error, "(workspace/symbol) #{exception}")
175+
request.reply_result([])
176+
end
177+
167178
else
168179
PuppetLanguageServer.log_message(:error, "Unknown RPC method #{request.rpc_method}")
169180
end

lib/puppet-languageserver/puppet_helper.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ def self.initialize_helper(options = {})
2626
sidecar_queue.cache = @inmemory_cache
2727
end
2828

29+
def self.all_objects(&_block)
30+
return nil if @default_types_loaded == false
31+
raise('Puppet Helper Cache has not been configured') if @inmemory_cache.nil?
32+
@inmemory_cache.all_objects do |key, item|
33+
yield key, item
34+
end
35+
end
36+
2937
# Node Graph
3038
def self.get_node_graph(content, local_workspace)
3139
with_temporary_file(content) do |filepath|

lib/puppet-languageserver/puppet_helper/cache.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ def objects_by_section(section, &_block)
7575
end
7676
end
7777

78+
def all_objects(&_block)
79+
@cache_lock.synchronize do
80+
@inmemory_cache.each do |item|
81+
yield item.key, item
82+
end
83+
end
84+
end
7885
private
7986

8087
# <Type of object in the file :function, :type, :class>

lib/puppet-languageserver/server_capabilities.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ def self.capabilities
44
# https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#initialize-request
55

66
{
7-
'textDocumentSync' => LanguageServer::TEXTDOCUMENTSYNCKIND_FULL,
8-
'hoverProvider' => true,
9-
'completionProvider' => {
7+
'textDocumentSync' => LanguageServer::TEXTDOCUMENTSYNCKIND_FULL,
8+
'hoverProvider' => true,
9+
'completionProvider' => {
1010
'resolveProvider' => true,
1111
'triggerCharacters' => ['>', '$', '[', '=']
1212
},
13-
'definitionProvider' => true,
14-
'documentSymbolProvider' => true
13+
'definitionProvider' => true,
14+
'documentSymbolProvider' => true,
15+
'workspaceSymbolProvider' => true
1516
}
1617
end
1718
end

0 commit comments

Comments
 (0)