Skip to content

Commit

Permalink
Merge pull request #166 from glennsarti/refactor-caching
Browse files Browse the repository at this point in the history
(GH-167) Refactor Language Server inmemory caching
  • Loading branch information
glennsarti authored Aug 22, 2019
2 parents 3511698 + d57c24e commit 6ee0252
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 246 deletions.
10 changes: 5 additions & 5 deletions lib/puppet-languageserver/manifest/completion_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def self.complete(content, line_num, char_num, options = {})
item_object = PuppetLanguageServer::PuppetHelper.get_type(item.type_name.value)
unless item_object.nil?
# Add Parameters
item_object.parameters.each_key do |name|
item_object.attributes.select { |_name, data| data[:type] == :param }.each_key do |name|
items << LSP::CompletionItem.new(
'label' => name.to_s,
'kind' => LSP::CompletionItemKind::PROPERTY,
Expand All @@ -71,7 +71,7 @@ def self.complete(content, line_num, char_num, options = {})
)
end
# Add Properties
item_object.properties.each_key do |name|
item_object.attributes.select { |_name, data| data[:type] == :property }.each_key do |name|
items << LSP::CompletionItem.new(
'label' => name.to_s,
'kind' => LSP::CompletionItemKind::PROPERTY,
Expand Down Expand Up @@ -249,7 +249,7 @@ def self.resolve(completion_item)
# The param/property list should initially sorted alphabetically
attr_names.sort!
# Add the 'ensure' param/property at the top if the resource supports it
attr_names.insert(0, 'ensure') unless item_type.allattrs.find_index(:ensure).nil?
attr_names.insert(0, 'ensure') unless item_type.attributes.keys.find_index(:ensure).nil?
# Get the longest string length for later hash-rocket padding
max_length = -1
attr_names.each { |name| max_length = name.length if name.length > max_length }
Expand All @@ -269,7 +269,7 @@ def self.resolve(completion_item)
when 'resource_parameter'
item_type = PuppetLanguageServer::PuppetHelper.get_type(data['resource_type'])
return result if item_type.nil?
param_type = item_type.parameters[data['param'].intern]
param_type = item_type.attributes[data['param'].intern]
unless param_type.nil?
# TODO: More things?
result.documentation = param_type[:doc] unless param_type[:doc].nil?
Expand All @@ -278,7 +278,7 @@ def self.resolve(completion_item)
when 'resource_property'
item_type = PuppetLanguageServer::PuppetHelper.get_type(data['resource_type'])
return result if item_type.nil?
prop_type = item_type.properties[data['prop'].intern]
prop_type = item_type.attributes[data['prop'].intern]
unless prop_type.nil?
# TODO: More things?
result.documentation = prop_type[:doc] unless prop_type[:doc].nil?
Expand Down
15 changes: 9 additions & 6 deletions lib/puppet-languageserver/manifest/document_symbol_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
module PuppetLanguageServer
module Manifest
module DocumentSymbolProvider
def self.workspace_symbols(query)
def self.workspace_symbols(query, object_cache)
query = '' if query.nil?
result = []
PuppetLanguageServer::PuppetHelper.all_objects do |key, item|
object_cache.all_objects do |key, item|
key_string = key.to_s
next unless key_string.include?(query)
next unless query.empty? || key_string.include?(query)
case item
when PuppetLanguageServer::PuppetHelper::PuppetType
when PuppetLanguageServer::Sidecar::Protocol::PuppetType
result << LSP::SymbolInformation.new(
'name' => key_string,
'kind' => LSP::SymbolKind::METHOD,
Expand All @@ -21,7 +21,7 @@ def self.workspace_symbols(query)
}
)

when PuppetLanguageServer::PuppetHelper::PuppetFunction
when PuppetLanguageServer::Sidecar::Protocol::PuppetFunction
result << LSP::SymbolInformation.new(
'name' => key_string,
'kind' => LSP::SymbolKind::FUNCTION,
Expand All @@ -32,7 +32,7 @@ def self.workspace_symbols(query)
}
)

when PuppetLanguageServer::PuppetHelper::PuppetClass
when PuppetLanguageServer::Sidecar::Protocol::PuppetClass
result << LSP::SymbolInformation.new(
'name' => key_string,
'kind' => LSP::SymbolKind::CLASS,
Expand All @@ -42,6 +42,9 @@ def self.workspace_symbols(query)
'range' => LSP.create_range(item.line, 0, item.line, 1024)
}
)

else
PuppetLanguageServer.log_message(:warn, "[Manifest::DocumentSymbolProvider] Unknown object type #{item.class}")
end
end
result
Expand Down
12 changes: 6 additions & 6 deletions lib/puppet-languageserver/manifest/hover_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ def self.resolve(content, line_num, char_num, options = {})
resource_object = PuppetLanguageServer::PuppetHelper.get_type(resource_type_name)
unless resource_object.nil?
# Check if it's a property
attribute = resource_object.properties.key?(item.attribute_name.intern)
if attribute != false
attribute = resource_object.attributes[item.attribute_name.intern]
if attribute[:type] == :property
content = get_attribute_type_property_content(resource_object, item.attribute_name.intern)
elsif resource_object.parameters.key?(item.attribute_name.intern)
elsif attribute[:type] == :param
content = get_attribute_type_parameter_content(resource_object, item.attribute_name.intern)
end
end
Expand Down Expand Up @@ -114,14 +114,14 @@ def self.get_fact_content(factname)
end

def self.get_attribute_type_parameter_content(item_type, param)
param_type = item_type.parameters[param]
param_type = item_type.attributes[param]
content = "**#{param}** Parameter"
content += "\n\n#{param_type[:doc]}" unless param_type[:doc].nil?
content
end

def self.get_attribute_type_property_content(item_type, property)
prop_type = item_type.properties[property]
prop_type = item_type.attributes[property]
content = "**#{property}** Property"
content += "\n\n(_required_)" if prop_type[:required?]
content += "\n\n#{prop_type[:doc]}" unless prop_type[:doc].nil?
Expand Down Expand Up @@ -161,7 +161,7 @@ def self.get_puppet_type_content(item_type)
content = "**#{item_type.key}** Resource\n\n"
content += "\n\n#{item_type.doc}" unless item_type.doc.nil?
content += "\n\n---\n"
item_type.allattrs.sort.each do |attr|
item_type.attributes.keys.sort.each do |attr|
content += "* #{attr}\n"
end

Expand Down
9 changes: 7 additions & 2 deletions lib/puppet-languageserver/message_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,12 @@ def receive_request(request)
begin
case documents.document_type(file_uri)
when :manifest
request.reply_result(PuppetLanguageServer::Manifest::SignatureProvider.signature_help(content, line_num, char_num, :tasks_mode => PuppetLanguageServer::DocumentStore.module_plan_file?(file_uri)))
request.reply_result(PuppetLanguageServer::Manifest::SignatureProvider.signature_help(
content,
line_num,
char_num,
:tasks_mode => PuppetLanguageServer::DocumentStore.plan_file?(file_uri)
))
else
raise "Unable to provide signatures on #{file_uri}"
end
Expand All @@ -199,7 +204,7 @@ def receive_request(request)
when 'workspace/symbol'
begin
result = []
result.concat(PuppetLanguageServer::Manifest::DocumentSymbolProvider.workspace_symbols(request.params['query']))
result.concat(PuppetLanguageServer::Manifest::DocumentSymbolProvider.workspace_symbols(request.params['query'], PuppetLanguageServer::PuppetHelper.cache))
request.reply_result(result)
rescue StandardError => e
PuppetLanguageServer.log_message(:error, "(workspace/symbol) #{e}")
Expand Down
12 changes: 2 additions & 10 deletions lib/puppet-languageserver/puppet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'pathname'
require 'tempfile'

%w[puppet_helper/cache_objects puppet_helper/cache].each do |lib|
%w[puppet_helper/cache].each do |lib|
begin
require "puppet-languageserver/#{lib}"
rescue LoadError
Expand All @@ -28,14 +28,6 @@ def self.initialize_helper(options = {})
sidecar_queue.cache = @inmemory_cache
end

def self.all_objects(&_block)
return nil if @default_types_loaded == false
raise('Puppet Helper Cache has not been configured') if @inmemory_cache.nil?
@inmemory_cache.all_objects do |key, item|
yield key, item
end
end

# Node Graph
def self.get_node_graph(content, local_workspace)
with_temporary_file(content) do |filepath|
Expand Down Expand Up @@ -174,8 +166,8 @@ def self.class_names
@inmemory_cache.object_names_by_section(:class).map(&:to_s)
end

# The object cache. Note this should only be used for testing
def self.cache
raise('Puppet Helper Cache has not been configured') if @inmemory_cache.nil?
@inmemory_cache
end

Expand Down
85 changes: 36 additions & 49 deletions lib/puppet-languageserver/puppet_helper/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,48 @@
module PuppetLanguageServer
module PuppetHelper
class Cache
SECTIONS = %i[class type function].freeze
ORIGINS = %i[default workspace].freeze

def initialize(_options = {})
@cache_lock = Mutex.new
@inmemory_cache = []
# The cache consists of an array of module PuppetLanguageServer::PuppetHelper objects
@inmemory_cache = {}
# The cache consists of hash of hashes
# @inmemory_cache[<origin>][<section>] = [ Array of SidecarProtocol Objects ]
end

def import_sidecar_list!(list, section, origin = nil)
section_object = section_to_object(section)
return if section_object.nil?
def import_sidecar_list!(list, section, origin)
return if origin.nil?
return if section.nil?
list = [] if list.nil?

@cache_lock.synchronize do
# Remove the existing items
@inmemory_cache.reject! { |item| item.is_a?(section_object) && (origin.nil? || item.origin == origin) }
# Append the list
list.each do |item|
object = sidecar_protocol_to_cache_object(item)
object.origin = origin
@inmemory_cache << object
end
remove_section_impl(section, origin)
# Set the list
@inmemory_cache[origin] = {} if @inmemory_cache[origin].nil?
@inmemory_cache[origin][section] = list
end
nil
end

def remove_section!(section, origin = nil)
section_object = section_to_object(section)
return if section_object.nil?

@cache_lock.synchronize do
@inmemory_cache.reject! { |item| item.is_a?(section_object) && (origin.nil? || item.origin == origin) }
remove_section_impl(section, origin)
end
nil
end

# section => <Type of object in the file :function, :type, :class>
def object_by_name(section, name)
name = name.intern if name.is_a?(String)
section_object = section_to_object(section)
return nil if section_object.nil?
return nil if section.nil?
@cache_lock.synchronize do
@inmemory_cache.each do |item|
next unless item.is_a?(section_object) && item.key == name
return item
@inmemory_cache.each do |_, sections|
next if sections[section].nil? || sections[section].empty?
sections[section].each do |item|
return item if item.key == name
end
end
end
nil
Expand All @@ -54,12 +53,11 @@ def object_by_name(section, name)
# section => <Type of object in the file :function, :type, :class>
def object_names_by_section(section)
result = []
section_object = section_to_object(section)
return result if section_object.nil?
return result if section.nil?
@cache_lock.synchronize do
@inmemory_cache.each do |item|
next unless item.is_a?(section_object)
result << item.key
@inmemory_cache.each do |_, sections|
next if sections[section].nil? || sections[section].empty?
result.concat(sections[section].map { |i| i.key })
end
end
result.uniq!
Expand All @@ -68,44 +66,33 @@ def object_names_by_section(section)

# section => <Type of object in the file :function, :type, :class>
def objects_by_section(section, &_block)
section_object = section_to_object(section)
return if section_object.nil?
return if section.nil?
@cache_lock.synchronize do
@inmemory_cache.each do |item|
next unless item.is_a?(section_object)
yield item.key, item
@inmemory_cache.each do |_, sections|
next if sections[section].nil? || sections[section].empty?
sections[section].each { |i| yield i.key, i }
end
end
end

def all_objects(&_block)
@cache_lock.synchronize do
@inmemory_cache.each do |item|
yield item.key, item
@inmemory_cache.each do |_origin, sections|
sections.each do |_section_name, list|
list.each { |i| yield i.key, i }
end
end
end
end

private

# <Type of object in the file :function, :type, :class>
def section_to_object(section)
case section
when :class
PuppetLanguageServer::PuppetHelper::PuppetClass
when :function
PuppetLanguageServer::PuppetHelper::PuppetFunction
when :type
PuppetLanguageServer::PuppetHelper::PuppetType
def remove_section_impl(section, origin = nil)
@inmemory_cache.each do |list_origin, sections|
next unless origin.nil? || list_origin == origin
sections[section].clear unless sections[section].nil?
end
end

def sidecar_protocol_to_cache_object(value)
return PuppetLanguageServer::PuppetHelper::PuppetClass.new.from_sidecar!(value) if value.is_a?(PuppetLanguageServer::Sidecar::Protocol::PuppetClass)
return PuppetLanguageServer::PuppetHelper::PuppetFunction.new.from_sidecar!(value) if value.is_a?(PuppetLanguageServer::Sidecar::Protocol::PuppetFunction)
return PuppetLanguageServer::PuppetHelper::PuppetType.new.from_sidecar!(value) if value.is_a?(PuppetLanguageServer::Sidecar::Protocol::PuppetType)
nil
end
end
end
end
48 changes: 0 additions & 48 deletions lib/puppet-languageserver/puppet_helper/cache_objects.rb

This file was deleted.

Loading

0 comments on commit 6ee0252

Please sign in to comment.