Skip to content

Commit 2cc861a

Browse files
author
James Pogran
authored
Merge pull request #86 from glennsarti/spike-add-workspace-symbols
(GH-88) Add workspace symbols provider
2 parents 4d7d1eb + 24fbfdd commit 2cc861a

File tree

7 files changed

+142
-6
lines changed

7 files changed

+142
-6
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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ 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
85+
7886
private
7987

8088
# <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

spec/languageserver/spec_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def wait_for_puppet_loading
2424
PuppetLanguageServer::PuppetHelper.default_classes_loaded?
2525
sleep(1)
2626
interation += 1
27-
next if interation < 60
27+
next if interation < 90
2828
raise <<-ERRORMSG
2929
Puppet has not be initialised in time:
3030
functions_loaded? = #{PuppetLanguageServer::PuppetHelper.default_functions_loaded?}

0 commit comments

Comments
 (0)