11require 'puppet/indirector/face'
22require 'pathname'
33
4- %w[ puppet_helper/faux_objects ] . each do |lib |
5- begin
6- require "puppet-languageserver/#{ lib } "
7- rescue LoadError
8- require File . expand_path ( File . join ( File . dirname ( __FILE__ ) , lib ) )
9- end
4+ %w[ puppet_helper/faux_objects puppet_helper/cache ] . each do |lib |
5+ begin
6+ require "puppet-languageserver/#{ lib } "
7+ rescue LoadError
8+ require File . expand_path ( File . join ( File . dirname ( __FILE__ ) , lib ) )
9+ end
1010end
1111
1212module PuppetLanguageServer
1313 module PuppetHelper
1414 # Reference - https://github.com/puppetlabs/puppet/blob/master/lib/puppet/reference/type.rb
1515
16- @ops_lock_types = Mutex . new
17- @ops_lock_funcs = Mutex . new
18- @ops_lock_classes = Mutex . new
19- @class_load_info = { }
20- @function_load_info = { }
21- @type_load_info = { }
22-
2316 @default_types_loaded = nil
2417 @default_functions_loaded = nil
2518 @default_classes_loaded = nil
19+ @inmemory_cache = nil
20+
21+ def self . configure_cache ( options = { } )
22+ @inmemory_cache = PuppetLanguageServer ::PuppetHelper ::Cache . new ( options )
23+ end
2624
2725 # Resource Face
2826 def self . resource_face_get_by_typename ( typename )
@@ -47,25 +45,20 @@ def self.types_loaded?
4745 end
4846
4947 def self . load_types
48+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
5049 _load_default_types
5150 end
5251
5352 def self . get_type ( name )
54- result = nil
55- return result if @default_types_loaded . nil?
56- @ops_lock_types . synchronize do
57- result = @type_load_info [ name . intern ]
58- end
59- result
53+ return nil if @default_types_loaded == false
54+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
55+ @inmemory_cache . object_by_name ( :type , name )
6056 end
6157
6258 def self . type_names
63- result = [ ]
64- return result if @default_types_loaded . nil?
65- @ops_lock_types . synchronize do
66- result = @type_load_info . keys . map ( &:to_s )
67- end
68- result
59+ return [ ] if @default_types_loaded == false
60+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
61+ @inmemory_cache . object_names_by_section ( :type ) . map ( &:to_s )
6962 end
7063
7164 # Functions
@@ -74,6 +67,7 @@ def self.functions_loaded?
7467 end
7568
7669 def self . load_functions
70+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
7771 _load_default_functions if @default_functions_loaded . nil?
7872 end
7973
@@ -84,33 +78,29 @@ def self.load_functions_async
8478 end
8579
8680 def self . filtered_function_names ( &block )
81+ return [ ] if @default_functions_loaded == false
82+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
83+ _load_default_functions if @default_functions_loaded . nil?
8784 result = [ ]
88- return result if @default_functions_loaded . nil?
89- @ops_lock_funcs . synchronize do
90- @function_load_info . each do |name , data |
91- filter = block . call ( name , data )
92- result << name if filter == true
93- end
85+ @inmemory_cache . objects_by_section ( :function ) do |name , data |
86+ filter = block . call ( name , data )
87+ result << name if filter == true
9488 end
9589 result
9690 end
9791
9892 def self . function ( name )
99- result = nil
100- return result if @default_functions_loaded . nil?
101- @ops_lock_funcs . synchronize do
102- result = @function_load_info [ name . intern ] . dup if @function_load_info . key? ( name . intern )
103- end
104- result
93+ return nil if @default_functions_loaded == false
94+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
95+ _load_default_functions unless @default_functions_loaded
96+ @inmemory_cache . object_by_name ( :function , name )
10597 end
10698
10799 def self . function_names
108- result = [ ]
109- return result if @default_functions_loaded . nil?
110- @ops_lock_funcs . synchronize do
111- result = @function_load_info . keys . map ( &:to_s )
112- end
113- result
100+ return [ ] if @default_functions_loaded == false
101+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
102+ _load_default_functions if @default_functions_loaded . nil?
103+ @inmemory_cache . object_names_by_section ( :function ) . map ( &:to_s )
114104 end
115105
116106 # Classes and Defined Types
@@ -119,24 +109,22 @@ def self.classes_loaded?
119109 end
120110
121111 def self . load_classes
112+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
122113 _load_default_classes if @default_classes_loaded . nil?
123114 end
124115
116+ def self . get_class ( name )
117+ return nil if @default_classes_loaded == false
118+ raise ( 'Puppet Helper Cache has not been configured' ) if @inmemory_cache . nil?
119+ @inmemory_cache . object_by_name ( :class , name )
120+ end
121+
125122 def self . load_classes_async
126123 Thread . new do
127124 load_classes
128125 end
129126 end
130127
131- def self . get_class ( name )
132- result = nil
133- return result if @default_classes_loaded . nil?
134- @ops_lock_funcs . synchronize do
135- result = @class_load_info [ name . intern ] . dup if @class_load_info . key? ( name . intern )
136- end
137- result
138- end
139-
140128 def self . prune_resource_parameters ( resources )
141129 # From https://github.com/puppetlabs/puppet/blob/488661d84e54904124514ab9e4500e81b10f84d1/lib/puppet/application/resource.rb#L146-L148
142130 if resources . is_a? ( Array )
@@ -199,6 +187,11 @@ def self._load_default_classes
199187 private_class_method :_load_default_classes
200188
201189 def self . load_classes_from_manifest ( manifest_file )
190+ # TODO: Add ignore cache switch
191+ return 0 if @inmemory_cache . exist? ( manifest_file , :class )
192+ return 0 if @inmemory_cache . load_from_persistent_cache! ( manifest_file )
193+ @inmemory_cache . set ( manifest_file , :class , nil )
194+
202195 file_content = File . open ( manifest_file , 'r:UTF-8' ) { |f | f . read }
203196
204197 parser = Puppet ::Pops ::Parser ::Parser . new
@@ -210,7 +203,7 @@ def self.load_classes_from_manifest(manifest_file)
210203 return 0
211204 end
212205
213- class_info_count = 0
206+ class_info = { }
214207 # Enumerate the entire AST looking for classes and defined types
215208 # TODO: Need to learn how to read the help/docs for hover support
216209 if result . model . respond_to? :eAllContents
@@ -233,10 +226,7 @@ def self.load_classes_from_manifest(manifest_file)
233226
234227 obj = FauxPuppetClass . new
235228 obj . from_puppet! ( item . name , puppet_class )
236- @ops_lock_classes . synchronize do
237- @class_load_info [ item . name . intern ] = obj
238- end
239- class_info_count += 1
229+ class_info [ item . name . intern ] = obj
240230 end
241231 else
242232 result . model . _pcore_all_contents ( [ ] ) do |item |
@@ -257,14 +247,12 @@ def self.load_classes_from_manifest(manifest_file)
257247
258248 obj = FauxPuppetClass . new
259249 obj . from_puppet! ( item . name , puppet_class )
260- @ops_lock_classes . synchronize do
261- @class_load_info [ item . name . intern ] = obj
262- end
263- class_info_count += 1
250+ class_info [ item . name . intern ] = obj
264251 end
265252 end
266253
267- class_info_count
254+ @inmemory_cache . set ( manifest_file , :class , class_info )
255+ class_info . count
268256 end
269257
270258 def self . load_type_file ( name , autoloader , env )
@@ -274,6 +262,9 @@ def self.load_type_file(name, autoloader, env)
274262 PuppetLanguageServer . log_message ( :warn , "[PuppetHelper::load_type_file] Could not find absolute path of type #{ name } " )
275263 return 0
276264 end
265+ # TODO: Add ignore cache switch
266+ return 0 if @inmemory_cache . exist? ( absolute_name , :type )
267+ return 0 if @inmemory_cache . load_from_persistent_cache! ( absolute_name )
277268
278269 # Get the list of currently loaded types
279270 loaded_types = [ ]
@@ -290,6 +281,7 @@ def self.load_type_file(name, autoloader, env)
290281 end
291282 end
292283
284+ @inmemory_cache . set ( absolute_name , :type , nil )
293285 unless autoloader . loaded? ( name )
294286 # This is an expensive call
295287 unless autoloader . load ( name )
@@ -298,7 +290,7 @@ def self.load_type_file(name, autoloader, env)
298290 end
299291
300292 # Find the types that were loaded
301- type_count = 0
293+ types = { }
302294 # Due to PUP-8301, if no types have been loaded yet then Puppet::Type.eachtype
303295 # will throw instead of not yielding.
304296 begin
@@ -308,10 +300,10 @@ def self.load_type_file(name, autoloader, env)
308300 next if item . name == :component || item . name == :whit
309301 obj = FauxType . new
310302 obj . from_puppet! ( item . name , item )
311- @ops_lock_types . synchronize do
312- @type_load_info [ obj . key ] = obj
313- end
314- type_count += 1
303+ # TODO: Need to use calling_source in the cache backing store
304+ # Perhaps I should be incrementally adding items to the cache instead of batch mode?
305+ obj . calling_source = absolute_name
306+ types [ obj . key ] = obj
315307 end
316308 rescue NoMethodError => detail
317309 # Detect PUP-8301
@@ -322,9 +314,10 @@ def self.load_type_file(name, autoloader, env)
322314 end
323315 end
324316
325- PuppetLanguageServer . log_message ( :warn , "[PuppetHelper::load_type_file] type #{ absolute_name } did not load any types" ) if type_count . zero?
317+ PuppetLanguageServer . log_message ( :warn , "[PuppetHelper::load_type_file] type #{ absolute_name } did not load any types" ) if types . empty?
318+ @inmemory_cache . set ( absolute_name , :type , types )
326319
327- type_count
320+ types . count
328321 end
329322 private_class_method :load_type_file
330323
@@ -361,9 +354,13 @@ def self.load_function_file(name, autoloader, env)
361354 PuppetLanguageServer . log_message ( :warn , "[PuppetHelper::load_function_file] Could not find absolute path of function #{ name } " )
362355 return 0
363356 end
357+ # TODO: Add ignore cache switch
358+ return 0 if @inmemory_cache . exist? ( absolute_name , :function )
359+ return 0 if @inmemory_cache . load_from_persistent_cache! ( absolute_name )
364360
365361 function_module = Puppet ::Parser ::Functions . environment_module ( env )
366362 function_count = 0
363+ @inmemory_cache . set ( absolute_name , :function , nil )
367364 unless autoloader . loaded? ( name )
368365 # This is an expensive call
369366 unless autoloader . load ( name , env )
@@ -379,14 +376,11 @@ def self.load_function_file(name, autoloader, env)
379376 obj = FauxFunction . new
380377 obj . from_puppet! ( func_name , item )
381378 obj . calling_source = absolute_name
382- @ops_lock_funcs . synchronize do
383- @function_load_info [ obj . key ] = obj
384- end
385-
386379 funcs [ obj . key ] = obj
387380 function_count += 1
388381 end
389382 PuppetLanguageServer . log_message ( :warn , "[PuppetHelper::load_function_file] file #{ absolute_name } did load any functions" ) if function_count . zero?
383+ @inmemory_cache . set ( absolute_name , :function , funcs )
390384
391385 function_count
392386 end
@@ -412,16 +406,17 @@ def self._load_default_functions
412406 filenames . uniq! . compact!
413407 # Now add the functions in each file to the cache
414408 filenames . each do |filename |
409+ @inmemory_cache . set ( filename , :function , nil )
410+ funcs = { }
415411 function_module . all_function_info
416412 . select { |_k , i | filename . casecmp ( i [ :source_location ] [ :source ] . to_s ) . zero? }
417413 . each do |name , item |
418414 obj = FauxFunction . new
419415 obj . from_puppet! ( name , item )
420- @ops_lock_funcs . synchronize do
421- @function_load_info [ obj . key ] = obj
422- end
416+ funcs [ obj . key ] = obj
423417 function_count += 1
424418 end
419+ @inmemory_cache . set ( filename , :function , funcs )
425420 end
426421
427422 # Now we can load functions from the default locations
0 commit comments