holistic-ruby 0.1.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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 }