Class: RubyLsp::Document Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_lsp/document.rb

Overview

This class is abstract.

: [ParseResultType]

Direct Known Subclasses

ERBDocument, RBSDocument, RubyDocument

Defined Under Namespace

Classes: Delete, Edit, Insert, InvalidLocationError, Replace, Scanner, Utf16Scanner, Utf32Scanner, Utf8Scanner

Constant Summary collapse

MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES =

This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics. This is the same number used by the TypeScript extension in VS Code

100_000
EMPTY_CACHE =

: Object

Object.new.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source:, version:, uri:, global_state:) ⇒ Document

: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ruby_lsp/document.rb', line 37

def initialize(source:, version:, uri:, global_state:)
  @source = source
  @version = version
  @global_state = global_state
  @cache = Hash.new(EMPTY_CACHE) #: Hash[String, untyped]
  @semantic_tokens = EMPTY_CACHE #: (Interface::SemanticTokens | Object)
  @encoding = global_state.encoding #: Encoding
  @uri = uri #: URI::Generic
  @needs_parsing = true #: bool
  @last_edit = nil #: Edit?

  # Workaround to be able to type parse_result properly. It is immediately set when invoking parse!
  @parse_result = ( # rubocop:disable Style/RedundantParentheses
    nil #: as untyped
  ) #: ParseResultType

  parse!
end

Instance Attribute Details

#encodingObject (readonly)

: Encoding



28
29
30
# File 'lib/ruby_lsp/document.rb', line 28

def encoding
  @encoding
end

#last_editObject (readonly)

: Edit?



31
32
33
# File 'lib/ruby_lsp/document.rb', line 31

def last_edit
  @last_edit
end

#parse_resultObject (readonly)

: ParseResultType



16
17
18
# File 'lib/ruby_lsp/document.rb', line 16

def parse_result
  @parse_result
end

#semantic_tokensObject

: (Interface::SemanticTokens | Object)



34
35
36
# File 'lib/ruby_lsp/document.rb', line 34

def semantic_tokens
  @semantic_tokens
end

#sourceObject (readonly)

: String



19
20
21
# File 'lib/ruby_lsp/document.rb', line 19

def source
  @source
end

#uriObject (readonly)

: URI::Generic



25
26
27
# File 'lib/ruby_lsp/document.rb', line 25

def uri
  @uri
end

#versionObject (readonly)

: Integer



22
23
24
# File 'lib/ruby_lsp/document.rb', line 22

def version
  @version
end

Instance Method Details

#==(other) ⇒ Object

: (Document other) -> bool



57
58
59
# File 'lib/ruby_lsp/document.rb', line 57

def ==(other)
  self.class == other.class && uri == other.uri && @source == other.source
end

#cache_fetch(request_name, &block) ⇒ Object

: [T] (String request_name) { (Document document) -> T } -> T



68
69
70
71
72
73
74
75
# File 'lib/ruby_lsp/document.rb', line 68

def cache_fetch(request_name, &block)
  cached = @cache[request_name]
  return cached if cached != EMPTY_CACHE

  result = block.call(self)
  @cache[request_name] = result
  result
end

#cache_get(request_name) ⇒ Object

: (String request_name) -> untyped



83
84
85
# File 'lib/ruby_lsp/document.rb', line 83

def cache_get(request_name)
  @cache[request_name]
end

#cache_set(request_name, value) ⇒ Object

: [T] (String request_name, T value) -> T



78
79
80
# File 'lib/ruby_lsp/document.rb', line 78

def cache_set(request_name, value)
  @cache[request_name] = value
end

#clear_cache(request_name) ⇒ Object

: (String request_name) -> void



88
89
90
# File 'lib/ruby_lsp/document.rb', line 88

def clear_cache(request_name)
  @cache[request_name] = EMPTY_CACHE
end

#find_index_by_position(start_pos, end_pos = nil) ⇒ Object

: (Hash[Symbol, untyped] start_pos, ?Hash[Symbol, untyped]? end_pos) -> [Integer, Integer?]



141
142
143
144
145
146
# File 'lib/ruby_lsp/document.rb', line 141

def find_index_by_position(start_pos, end_pos = nil)
  scanner = create_scanner
  start_index = scanner.find_char_position(start_pos)
  end_index = scanner.find_char_position(end_pos) if end_pos
  [start_index, end_index]
end

#language_idObject

This method is abstract.

: -> Symbol



63
64
65
# File 'lib/ruby_lsp/document.rb', line 63

def language_id
  raise AbstractMethodInvokedError
end

#parse!Object

This method is abstract.

Returns ‘true` if the document was parsed and `false` if nothing needed parsing : -> bool



125
126
127
# File 'lib/ruby_lsp/document.rb', line 125

def parse!
  raise AbstractMethodInvokedError
end

#past_expensive_limit?Boolean

: -> bool

Returns:

  • (Boolean)


136
137
138
# File 'lib/ruby_lsp/document.rb', line 136

def past_expensive_limit?
  @source.length > MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES
end

#push_edits(edits, version:) ⇒ Object

: (Array[Hash[Symbol, untyped]] edits, version: Integer) -> void



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ruby_lsp/document.rb', line 93

def push_edits(edits, version:)
  edits.each do |edit|
    range = edit[:range]
    scanner = create_scanner

    start_position = scanner.find_char_position(range[:start])
    end_position = scanner.find_char_position(range[:end])

    @source[start_position...end_position] = edit[:text]
  end

  @version = version
  @needs_parsing = true
  @cache.clear

  last_edit = edits.last
  return unless last_edit

  last_edit_range = last_edit[:range]

  @last_edit = if last_edit_range[:start] == last_edit_range[:end]
    Insert.new(last_edit_range)
  elsif last_edit[:text].empty?
    Delete.new(last_edit_range)
  else
    Replace.new(last_edit_range)
  end
end

#syntax_error?Boolean

This method is abstract.

: -> bool

Returns:

  • (Boolean)

Raises:



131
132
133
# File 'lib/ruby_lsp/document.rb', line 131

def syntax_error?
  raise AbstractMethodInvokedError
end