holistic-ruby 0.1.1 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +1 -1
  4. data/lib/holistic/application.rb +12 -4
  5. data/lib/holistic/database/migrations.rb +20 -0
  6. data/lib/holistic/database/node.rb +29 -0
  7. data/lib/holistic/database/table.rb +53 -53
  8. data/lib/holistic/document/file/record.rb +10 -0
  9. data/lib/holistic/document/file/repository.rb +24 -0
  10. data/lib/holistic/document/file/store.rb +13 -0
  11. data/lib/holistic/document/location.rb +4 -6
  12. data/lib/holistic/document/unsaved/record.rb +0 -4
  13. data/lib/holistic/extensions/events.rb +9 -1
  14. data/lib/holistic/extensions/ruby/stdlib.rb +26 -12
  15. data/lib/holistic/language_server/requests/lifecycle/initialize.rb +5 -10
  16. data/lib/holistic/language_server/requests/text_document/completion.rb +11 -8
  17. data/lib/holistic/language_server/requests/text_document/did_close.rb +6 -12
  18. data/lib/holistic/language_server/requests/text_document/did_open.rb +1 -0
  19. data/lib/holistic/language_server/requests/text_document/did_save.rb +5 -9
  20. data/lib/holistic/language_server/requests/text_document/find_references.rb +7 -4
  21. data/lib/holistic/language_server/requests/text_document/go_to_definition.rb +3 -2
  22. data/lib/holistic/ruby/autocompletion/suggest.rb +65 -15
  23. data/lib/holistic/ruby/parser/constant_resolution.rb +60 -9
  24. data/lib/holistic/ruby/parser/live_editing/process_file_changed.rb +24 -21
  25. data/lib/holistic/ruby/parser/nesting_syntax.rb +1 -0
  26. data/lib/holistic/ruby/parser/program_visitor.rb +57 -44
  27. data/lib/holistic/ruby/parser.rb +14 -9
  28. data/lib/holistic/ruby/reference/delete.rb +18 -0
  29. data/lib/holistic/ruby/reference/find_referenced_scope.rb +2 -2
  30. data/lib/holistic/ruby/reference/record.rb +7 -8
  31. data/lib/holistic/ruby/reference/repository.rb +19 -41
  32. data/lib/holistic/ruby/reference/store.rb +18 -0
  33. data/lib/holistic/ruby/scope/delete.rb +29 -0
  34. data/lib/holistic/ruby/scope/kind.rb +6 -5
  35. data/lib/holistic/ruby/scope/lexical.rb +11 -0
  36. data/lib/holistic/ruby/scope/list_references.rb +2 -2
  37. data/lib/holistic/ruby/scope/location.rb +9 -9
  38. data/lib/holistic/ruby/scope/outline.rb +8 -8
  39. data/lib/holistic/ruby/scope/record.rb +15 -47
  40. data/lib/holistic/ruby/scope/repository.rb +24 -25
  41. data/lib/holistic/ruby/scope/store.rb +45 -0
  42. data/lib/holistic/ruby/type_inference/processing_queue.rb +19 -0
  43. data/lib/holistic/ruby/type_inference/solve.rb +23 -21
  44. data/lib/holistic/ruby/type_inference/solve_pending_references.rb +3 -1
  45. data/lib/holistic/version.rb +1 -1
  46. metadata +13 -9
  47. data/lib/holistic/document/file.rb +0 -36
  48. data/lib/holistic/ruby/parser/table_of_contents.rb +0 -17
  49. data/lib/holistic/ruby/reference/register.rb +0 -15
  50. data/lib/holistic/ruby/reference/unregister.rb +0 -11
  51. data/lib/holistic/ruby/scope/register.rb +0 -31
  52. data/lib/holistic/ruby/scope/unregister.rb +0 -27
  53. data/lib/holistic/ruby/type_inference/conclusion.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 601bd799099f6615186f5d70dafab227a2f5d59e556aedec607784fc289b9f23
4
- data.tar.gz: 8684f179e1cf58b47d4cac81c75c10113c46f5578a9ab1ecd74eddcad2e20259
3
+ metadata.gz: 43d41e307a4ae8b8b904fda778342ef5d175db25580697f597f606f3aa2a0173
4
+ data.tar.gz: 5286406cf4e0f5a5cb21745b3f7d49268eb934e4002e76d1ba43f9dfdda034fd
5
5
  SHA512:
6
- metadata.gz: 6cc033aaddc4b86f6b733c17c7cea974fabcc68132b7f7776dcbe9bdf4f6222ed52d6e58694e9988d624b693eab3d6abcf28389d5208b41221fee511e33c486e
7
- data.tar.gz: 54ebf824ec6771d1b58146a6c958a9271e229daa5c2d0c3a23830a873be8ffc523065f06a0240d821256712dd2c31c7136a7bf6e38fb7552eab4124bec24b5c8
6
+ metadata.gz: 882cac6ec7c32d309898aab43f001a3fcf0e497b6c019569472db3880b792e95fe50158b8672690c80237e0a9c6ac361ede5b79a09e2784ddc944d103c54eaba
7
+ data.tar.gz: 64e1becad926aba30e7c9f25b294a2ff9b53dcdfe7affc5e59792054cf21b17b3509eb7fc80e1819fecc9f7d7e22957df3bda2c03990b9e77476c3bc1fa956e0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- holistic-ruby (0.1.0)
4
+ holistic-ruby (0.1.4)
5
5
  activesupport (~> 7.0)
6
6
  syntax_tree (~> 6.0)
7
7
  zeitwerk (~> 2.6)
data/README.md CHANGED
@@ -32,4 +32,4 @@
32
32
 
33
33
  ## Why is it a toy language server?
34
34
 
35
- I use `holistic-ruby` on a daily basis in a faily large Ruby codebase. It seems stable and speedy. But... I built it for myself and I'm the only one using it :smile:
35
+ I use `holistic-ruby` on a daily basis while working in a fairly large Ruby codebase. It seems stable and speedy. But... I built it for myself and I'm the only one using it :smile:
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Holistic
4
4
  class Application
5
- attr_reader :name, :root_directory, :root_scope
5
+ attr_reader :name, :root_directory, :database
6
6
 
7
7
  def initialize(name:, root_directory:)
8
8
  @name = name
9
9
  @root_directory = root_directory
10
- @root_scope = Ruby::Scope::Record.new(kind: Ruby::Scope::Kind::ROOT, name: "::", parent: nil)
10
+ @database = Database::Table.new.tap(&Database::Migrations::Run)
11
11
  end
12
12
 
13
13
  def extensions
@@ -15,11 +15,19 @@ module Holistic
15
15
  end
16
16
 
17
17
  def scopes
18
- @scopes ||= Ruby::Scope::Repository.new
18
+ @scopes ||= Ruby::Scope::Repository.new(database:)
19
19
  end
20
20
 
21
21
  def references
22
- @references ||= Ruby::Reference::Repository.new
22
+ @references ||= Ruby::Reference::Repository.new(database:)
23
+ end
24
+
25
+ def files
26
+ @files ||= Document::File::Repository.new(database:)
27
+ end
28
+
29
+ def type_inference_processing_queue
30
+ @type_inference_processing_queue ||= Ruby::TypeInference::ProcessingQueue.new
23
31
  end
24
32
 
25
33
  def unsaved_documents
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holistic::Database::Migrations
4
+ Run = ->(database) do
5
+ # scope parent-children relation
6
+ database.define_connection(name: :children, inverse_of: :parent)
7
+
8
+ # type inference conclusion
9
+ database.define_connection(name: :referenced_scope, inverse_of: :referenced_by)
10
+
11
+ # reference definition
12
+ database.define_connection(name: :located_in_scope, inverse_of: :contains_many_references)
13
+
14
+ # scope location in files
15
+ database.define_connection(name: :defines_scopes, inverse_of: :scope_defined_in_file)
16
+
17
+ # reference location in files
18
+ database.define_connection(name: :defines_references, inverse_of: :reference_defined_in_file)
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holistic::Database
4
+ class Node
5
+ attr_accessor :attributes, :connections, :__database__
6
+
7
+ def initialize(id, attributes)
8
+ @id = id
9
+ @attributes = attributes
10
+ @connections = ::Hash.new { |hash, key| hash[key] = ::Set.new }
11
+ end
12
+
13
+ def attr(attribute_name)
14
+ @attributes[attribute_name]
15
+ end
16
+
17
+ def has_many(connection_name)
18
+ @connections[connection_name].to_a
19
+ end
20
+
21
+ def has_one(connection_name)
22
+ @connections[connection_name].first
23
+ end
24
+
25
+ def __set_database__(database)
26
+ @__database__ = database
27
+ end
28
+ end
29
+ end
@@ -1,78 +1,78 @@
1
- # frozen_string_literal: true
2
-
3
- class Holistic::Database::Table
4
- attr_reader :primary_attribute, :primary_index, :secondary_indices
5
-
6
- def initialize(primary_attribute:, indices: [])
7
- @primary_attribute = primary_attribute
8
1
 
9
- @primary_index = ::Hash.new
2
+ # frozen_string_literal: true
10
3
 
11
- @secondary_indices = indices.map do |attribute_name|
12
- [attribute_name, ::Hash.new { |hash, key| hash[key] = ::Set.new }]
13
- end.to_h
14
- end
4
+ module Holistic::Database
5
+ class Table
6
+ attr_reader :records, :connections
15
7
 
16
- RecordNotUniqueError = ::Class.new(::StandardError)
8
+ def initialize
9
+ @records = ::Hash.new
10
+ @connections = ::Hash.new
11
+ end
17
12
 
18
- def insert(record)
19
- primary_key = record.fetch(primary_attribute)
13
+ def define_connection(name:, inverse_of:)
14
+ raise ::ArgumentError if @connections.key?(name) || @connections.key?(inverse_of)
20
15
 
21
- if primary_index.key?(primary_key)
22
- raise RecordNotUniqueError, "record already inserted: #{record.inspect}"
16
+ @connections[name] = { inverse_of: }
17
+ @connections[inverse_of] = { inverse_of: name }
23
18
  end
24
19
 
25
- primary_index[primary_key] = record
26
-
27
- secondary_indices.each do |attribute_name, secondary_index|
28
- Array(record[attribute_name]).each do |value|
29
- secondary_index[value].add(primary_key)
20
+ def store(id, node_or_attrs)
21
+ if @records.key?(id)
22
+ return @records[id]&.tap do |node|
23
+ node.attributes =
24
+ case node_or_attrs
25
+ in ::Hash then node_or_attrs
26
+ in Node then node_or_attrs.attributes
27
+ end
28
+ end
30
29
  end
31
- end
32
- end
33
30
 
34
- def find(identifier)
35
- primary_index[identifier]
36
- end
31
+ node =
32
+ case node_or_attrs
33
+ in ::Hash then Node.new(id, node_or_attrs)
34
+ in Node then node_or_attrs
35
+ end
37
36
 
38
- def filter(name, value)
39
- return [] unless secondary_indices[name].key?(value)
37
+ node.__set_database__(self)
40
38
 
41
- secondary_indices.dig(name, value).to_a.map { find(_1) }
42
- end
43
-
44
- def update(record)
45
- primary_key = record.fetch(primary_attribute)
39
+ @records[id] = node
40
+ end
46
41
 
47
- delete(primary_key)
42
+ def connect(source:, target:, name:, inverse_of:)
43
+ connection = @connections[name]
48
44
 
49
- insert(record)
50
- end
45
+ raise ::ArgumentError if connection.nil? || connection[:inverse_of] != inverse_of
51
46
 
52
- def delete(primary_key)
53
- record = find(primary_key)
47
+ source.connections[name].add(target)
48
+ target.connections[inverse_of].add(source)
49
+ end
54
50
 
55
- return if record.nil?
51
+ def disconnect(source:, target:, name:, inverse_of:)
52
+ connection = @connections[name]
56
53
 
57
- primary_index.delete(primary_key)
54
+ raise ::ArgumentError if connection.nil? || connection[:inverse_of] != inverse_of
58
55
 
59
- secondary_indices.each do |attribute_name, index_data|
60
- Array(record[attribute_name]).each do |value|
61
- index_data[value].delete(primary_key)
62
- index_data.delete(value) if index_data[value].empty?
63
- end
56
+ source.connections[name].delete(target)
57
+ target.connections[inverse_of].delete(source)
64
58
  end
65
59
 
66
- record
67
- end
60
+ def find(id)
61
+ @records[id]
62
+ end
68
63
 
69
- concerning :TestHelpers do
70
- def all
71
- primary_index.values
64
+ def delete(id)
65
+ records.delete(id)
72
66
  end
73
67
 
74
- def size
75
- primary_index.size
68
+ concerning :TestHelpers do
69
+ def all
70
+ records.values
71
+ end
72
+
73
+ def size
74
+ records.size
75
+ end
76
76
  end
77
77
  end
78
78
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holistic::Document::File
4
+ class Record < ::Holistic::Database::Node
5
+ def path = attr(:path)
6
+
7
+ def defines_scopes = has_many(:defines_scopes)
8
+ def defines_references = has_many(:defines_references)
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ::Holistic::Document::File
4
+ class Repository
5
+ attr_reader :database
6
+
7
+ def initialize(database:)
8
+ @database = database
9
+ end
10
+
11
+ # rename to `find_file`
12
+ def find(file_path)
13
+ @database.find(file_path)
14
+ end
15
+
16
+ concerning :TestHelpers do
17
+ def build_fake_location(file_path)
18
+ file = Store.call(database:, file_path:)
19
+
20
+ ::Holistic::Document::Location.new(file, 0, 0, 0, 0)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holistic::Document::File
4
+ module Store
5
+ extend self
6
+
7
+ def call(database:, file_path:)
8
+ record = Record.new(file_path, { path: file_path })
9
+
10
+ database.store(file_path, record)
11
+ end
12
+ end
13
+ end
@@ -2,20 +2,18 @@
2
2
 
3
3
  module Holistic::Document
4
4
  Location = ::Data.define(
5
- :file_path,
5
+ :file,
6
6
  :start_line,
7
7
  :start_column,
8
8
  :end_line,
9
9
  :end_column
10
10
  ) do
11
- def self.beginning_of_file(file_path)
12
- new(file_path, 0, 0, 0, 0)
11
+ def identifier
12
+ "#{file.path}[#{start_line},#{start_column},#{end_line},#{end_column}]"
13
13
  end
14
14
 
15
- def identifier = "#{file_path}[#{start_line},#{start_column},#{end_line},#{end_column}]"
16
-
17
15
  def contains?(cursor)
18
- same_file = cursor.file_path == file_path
16
+ same_file = cursor.file_path == file.path
19
17
  contains_line = cursor.line >= start_line && cursor.line <= end_line
20
18
 
21
19
  contains_column =
@@ -75,9 +75,5 @@ module Holistic::Document
75
75
  end
76
76
  end
77
77
  end
78
-
79
- def to_file
80
- File::Fake.new(path:, content:)
81
- end
82
78
  end
83
79
  end
@@ -5,6 +5,14 @@ class Holistic::Extensions::Events
5
5
  resolve_method_call_known_scope: {
6
6
  params: [:reference, :referenced_scope, :method_call_clue],
7
7
  output: ::Holistic::Ruby::Scope::Record
8
+ },
9
+ class_scope_registered: {
10
+ params: [:class_scope, :location],
11
+ output: nil
12
+ },
13
+ lambda_scope_registered: {
14
+ params: [:lambda_scope, :location],
15
+ output: nil
8
16
  }
9
17
  }.freeze
10
18
 
@@ -30,7 +38,7 @@ class Holistic::Extensions::Events
30
38
 
31
39
  result = @listeners[event].lazy.filter_map { |callback| callback.call(params) }.first
32
40
 
33
- raise UnexpectedOutput, result if result.present? && !result.is_a?(expected_output)
41
+ raise UnexpectedOutput, result if expected_output.present? && result.present? && !result.is_a?(expected_output)
34
42
 
35
43
  result
36
44
  end
@@ -10,34 +10,48 @@ module Holistic::Extensions::Ruby
10
10
  if method_call_clue.method_name == "new" && referenced_scope.class?
11
11
  initialize_method = "#{referenced_scope.fully_qualified_name}#initialize"
12
12
 
13
- return application.scopes.find_by_fully_qualified_name(initialize_method)
13
+ return application.scopes.find(initialize_method)
14
14
  end
15
15
 
16
16
  nil
17
17
  end
18
18
 
19
- ResolveStaticMethods = ->(application, params) do
20
- method_call_clue, referenced_scope = params[:method_call_clue], params[:referenced_scope]
19
+ RegisterClassConstructor = ->(application, params) do
20
+ class_scope, location = params[:class_scope], params[:location]
21
21
 
22
- self_method_name = "#{referenced_scope.fully_qualified_name}#self.#{method_call_clue.method_name}"
22
+ has_overridden_new_method = class_scope.children.find { _1.instance_method? && _1.name == "initialize" }
23
23
 
24
- application.scopes.find_by_fully_qualified_name(self_method_name)
24
+ unless has_overridden_new_method
25
+ ::Holistic::Ruby::Scope::Store.call(
26
+ database: application.database,
27
+ parent: class_scope,
28
+ kind: ::Holistic::Ruby::Scope::Kind::CLASS_METHOD,
29
+ name: "new",
30
+ location:
31
+ )
32
+ end
25
33
  end
26
34
 
27
- LAMBDA_METHODS = ["call", "curry"]
35
+ LAMBDA_METHODS = ["call", "curry"].freeze
28
36
 
29
- ResolveCallToLambda = ->(application, params) do
30
- method_call_clue, referenced_scope = params[:method_call_clue], params[:referenced_scope]
37
+ RegisterLambdaMethods = ->(application, params) do
38
+ lambda_scope, location = params[:lambda_scope], params[:location]
31
39
 
32
- if LAMBDA_METHODS.include?(method_call_clue.method_name) && referenced_scope.lambda?
33
- return referenced_scope
40
+ LAMBDA_METHODS.each do |method_name|
41
+ ::Holistic::Ruby::Scope::Store.call(
42
+ database: application.database,
43
+ parent: lambda_scope,
44
+ kind: ::Holistic::Ruby::Scope::Kind::CLASS_METHOD,
45
+ name: method_name,
46
+ location:
47
+ )
34
48
  end
35
49
  end
36
50
 
37
51
  def register(application)
38
52
  application.extensions.bind(:resolve_method_call_known_scope, &ResolveClassConstructor.curry[application])
39
- application.extensions.bind(:resolve_method_call_known_scope, &ResolveStaticMethods.curry[application])
40
- application.extensions.bind(:resolve_method_call_known_scope, &ResolveCallToLambda.curry[application])
53
+ application.extensions.bind(:class_scope_registered, &RegisterClassConstructor.curry[application])
54
+ application.extensions.bind(:lambda_scope_registered, &RegisterLambdaMethods.curry[application])
41
55
  end
42
56
  end
43
57
  end
@@ -14,23 +14,18 @@ module Holistic::LanguageServer
14
14
 
15
15
  parse_application_in_background(application)
16
16
 
17
- respond_with_holistic_capabilities(request)
17
+ respond_with_language_server_capabilities(request)
18
18
  end
19
19
 
20
20
  private
21
21
 
22
22
  def create_application(request)
23
- ::Holistic.logger.info("===========")
24
- ::Holistic.logger.info(request.message.inspect)
25
-
26
23
  root_directory = request.param("rootPath")
27
24
  name = ::File.basename(root_directory)
28
25
 
29
- Current.application = ::Holistic::Application.new(name:, root_directory:)
30
-
31
- ::Holistic::Extensions::Ruby::Stdlib.register(Current.application)
32
-
33
- Current.application
26
+ Current.application = ::Holistic::Application.new(name:, root_directory:).tap do |application|
27
+ ::Holistic::Extensions::Ruby::Stdlib.register(application)
28
+ end
34
29
  end
35
30
 
36
31
  def advance_lifecycle_state
@@ -45,7 +40,7 @@ module Holistic::LanguageServer
45
40
  end
46
41
  end
47
42
 
48
- def respond_with_holistic_capabilities(request)
43
+ def respond_with_language_server_capabilities(request)
49
44
  request.respond_with({
50
45
  capabilities: {
51
46
  # Defines how the host (editor) should sync document changes to the language server.
@@ -8,21 +8,23 @@ module Holistic::LanguageServer
8
8
  cursor = build_cursor_from_request_params(request)
9
9
 
10
10
  document = request.application.unsaved_documents.find(cursor.file_path)
11
-
11
+
12
12
  return request.respond_with(nil) if document.nil?
13
13
 
14
14
  if document.has_unsaved_changes?
15
15
  ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(
16
16
  application: request.application,
17
- file: document.to_file
17
+ file_path: document.path,
18
+ content: document.content
18
19
  )
19
20
  end
20
21
 
21
22
  code = document.expand_code(cursor)
22
- scope = request.application.scopes.find_inner_most_scope_by_cursor(cursor) || request.application.root_scope
23
23
 
24
24
  return request.respond_with(nil) if code.blank?
25
25
 
26
+ scope = request.application.scopes.find_inner_most_scope_by_cursor(cursor) || request.application.scopes.root
27
+
26
28
  suggestions = ::Holistic::Ruby::Autocompletion::Suggest.call(code:, scope:)
27
29
 
28
30
  respond_with_suggestions(request, suggestions)
@@ -40,11 +42,12 @@ module Holistic::LanguageServer
40
42
 
41
43
  module CompletionKind
42
44
  FROM_SCOPE_TO_COMPLETION = {
43
- ::Holistic::Ruby::Scope::Kind::CLASS => Protocol::COMPLETION_ITEM_KIND_CLASS,
44
- ::Holistic::Ruby::Scope::Kind::LAMBDA => Protocol::COMPLETION_ITEM_KIND_FUNCTION,
45
- ::Holistic::Ruby::Scope::Kind::METHOD => Protocol::COMPLETION_ITEM_KIND_METHOD,
46
- ::Holistic::Ruby::Scope::Kind::MODULE => Protocol::COMPLETION_ITEM_KIND_MODULE,
47
- ::Holistic::Ruby::Scope::Kind::ROOT => Protocol::COMPLETION_ITEM_KIND_MODULE
45
+ ::Holistic::Ruby::Scope::Kind::CLASS => Protocol::COMPLETION_ITEM_KIND_CLASS,
46
+ ::Holistic::Ruby::Scope::Kind::LAMBDA => Protocol::COMPLETION_ITEM_KIND_FUNCTION,
47
+ ::Holistic::Ruby::Scope::Kind::CLASS_METHOD => Protocol::COMPLETION_ITEM_KIND_METHOD,
48
+ ::Holistic::Ruby::Scope::Kind::INSTANCE_METHOD => Protocol::COMPLETION_ITEM_KIND_METHOD,
49
+ ::Holistic::Ruby::Scope::Kind::MODULE => Protocol::COMPLETION_ITEM_KIND_MODULE,
50
+ ::Holistic::Ruby::Scope::Kind::ROOT => Protocol::COMPLETION_ITEM_KIND_MODULE
48
51
  }.freeze
49
52
 
50
53
  DEFAULT = Protocol::COMPLETION_ITEM_KIND_MODULE
@@ -7,27 +7,21 @@ module Holistic::LanguageServer
7
7
  def call(request)
8
8
  path = Format::FileUri.extract_path(request.message.param("textDocument", "uri"))
9
9
 
10
- unsaved_document = request.application.unsaved_documents.find(path)
11
-
12
- if unsaved_document.present?
10
+ request.application.unsaved_documents.find(path)&.then do |unsaved_document|
13
11
  request.application.unsaved_documents.delete(path)
14
12
 
15
13
  if unsaved_document.has_unsaved_changes?
16
14
  unsaved_document.restore_original_content!
17
15
 
18
- process_in_background(application: request.application, file: unsaved_document.to_file)
16
+ ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(
17
+ application: request.application,
18
+ file_path: unsaved_document.path,
19
+ content: unsaved_document.content
20
+ )
19
21
  end
20
22
  end
21
23
 
22
24
  request.respond_with(nil)
23
25
  end
24
-
25
- private
26
-
27
- def process_in_background(application:, file:)
28
- ::Holistic::BackgroundProcess.run do
29
- ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(application:, file:)
30
- end
31
- end
32
26
  end
33
27
  end
@@ -9,6 +9,7 @@ module Holistic::LanguageServer
9
9
  content = request.message.param("textDocument", "text")
10
10
 
11
11
  request.application.unsaved_documents.add(path:, content:)
12
+ ::Holistic::Document::File::Store.call(database: request.application.database, file_path: path)
12
13
 
13
14
  request.respond_with(nil)
14
15
  end
@@ -17,17 +17,13 @@ module Holistic::LanguageServer
17
17
 
18
18
  unsaved_document.mark_as_saved!
19
19
 
20
- process_in_background(application: request.application, file: unsaved_document.to_file)
20
+ ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(
21
+ application: request.application,
22
+ file_path: unsaved_document.path,
23
+ content: unsaved_document.content
24
+ )
21
25
 
22
26
  request.respond_with(nil)
23
27
  end
24
-
25
- private
26
-
27
- def process_in_background(application:, file:)
28
- ::Holistic::BackgroundProcess.run do
29
- ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(application:, file:)
30
- end
31
- end
32
28
  end
33
29
  end
@@ -12,7 +12,8 @@ module Holistic::LanguageServer
12
12
  if unsaved_document.has_unsaved_changes?
13
13
  ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(
14
14
  application: request.application,
15
- file: unsaved_document.to_file
15
+ file_path: unsaved_document.path,
16
+ content: unsaved_document.content
16
17
  )
17
18
  end
18
19
  end
@@ -37,11 +38,13 @@ module Holistic::LanguageServer
37
38
 
38
39
  def respond_with_locations(request, references)
39
40
  locations = references.map do |reference|
41
+ location = reference.location
42
+
40
43
  {
41
- "uri" => Format::FileUri.from_path(reference.location.file_path),
44
+ "uri" => Format::FileUri.from_path(location.file.path),
42
45
  "range" => {
43
- "start" => { "line" => reference.location.start_line, "character" => reference.location.start_column },
44
- "end" => { "line" => reference.location.end_line, "character" => reference.location.end_column }
46
+ "start" => { "line" => location.start_line, "character" => location.start_column },
47
+ "end" => { "line" => location.end_line, "character" => location.end_column }
45
48
  }
46
49
  }
47
50
  end
@@ -12,7 +12,8 @@ module Holistic::LanguageServer
12
12
  if unsaved_document.has_unsaved_changes?
13
13
  ::Holistic::Ruby::Parser::LiveEditing::ProcessFileChanged.call(
14
14
  application: request.application,
15
- file: unsaved_document.to_file
15
+ file_path: unsaved_document.path,
16
+ content: unsaved_document.content
16
17
  )
17
18
  end
18
19
  end
@@ -46,7 +47,7 @@ module Holistic::LanguageServer
46
47
  "start" => { "line" => origin_location.start_line, "character" => origin_location.start_column },
47
48
  "end" => { "line" => origin_location.end_line, "character" => origin_location.end_column }
48
49
  },
49
- "targetUri" => Format::FileUri.from_path(target_declaration_location.file_path),
50
+ "targetUri" => Format::FileUri.from_path(target_declaration_location.file.path),
50
51
  "targetRange" => {
51
52
  "start" => { "line" => target_declaration_location.start_line, "character" => target_declaration_location.start_column },
52
53
  "end" => { "line" => target_declaration_location.end_line, "character" => target_declaration_location.end_column }