Class: ThemeCheck::LanguageServer::DocumentChangeCorrector

Inherits:
Object
  • Object
show all
Includes:
JsonHelpers, URIHelper
Defined in:
lib/theme_check/language_server/document_change_corrector.rb

Instance Method Summary collapse

Methods included from JsonHelpers

#format_json_parse_error, #pretty_json

Methods included from URIHelper

#file_path, #file_uri

Constructor Details

#initializeDocumentChangeCorrector

Returns a new instance of DocumentChangeCorrector.



9
10
11
12
13
14
15
16
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 9

def initialize
  @json_edits = {}
  @json_file_edits = {}
  @text_document_edits = {}
  @create_files = []
  @rename_files = []
  @delete_files = []
end

Instance Method Details

#add_translation(file, path, value) ⇒ Object

Raises:

  • (ArgumentError)


142
143
144
145
146
147
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 142

def add_translation(file, path, value)
  raise ArgumentError unless file.is_a?(JsonFile)
  hash = file.content
  SchemaHelper.set(hash, path, value)
  @json_file_edits[file] = hash
end

#create_file(storage, relative_path, contents = nil, overwrite: false) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 110

def create_file(storage, relative_path, contents = nil, overwrite: false)
  uri = file_uri(storage.path(relative_path))
  @create_files << create_file_change(uri, overwrite)
  return if contents.nil?
  text_document = { uri: uri, version: nil }
  @text_document_edits[text_document] = {
    textDocument: text_document,
    edits: [{
      range: {
        start: { line: 0, character: 0 },
        end: { line: 0, character: 0 },
      },
      newText: contents,
    }],
  }
end

#document_changesObject



18
19
20
21
22
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 18

def document_changes
  apply_json_edits
  apply_json_file_edits
  @create_files + @rename_files + @text_document_edits.values + @delete_files
end

#insert_after(node, content, character_range = nil) ⇒ Object

Parameters:



37
38
39
40
41
42
43
44
45
46
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 37

def insert_after(node, content, character_range = nil)
  position = character_range_position(node, character_range) if character_range
  edits(node) << {
    range: {
      start: end_location(position || node),
      end: end_location(position || node),
    },
    newText: content,
  }
end

#insert_before(node, content, character_range = nil) ⇒ Object

Parameters:



25
26
27
28
29
30
31
32
33
34
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 25

def insert_before(node, content, character_range = nil)
  position = character_range_position(node, character_range) if character_range
  edits(node) << {
    range: {
      start: start_location(position || node),
      end: start_location(position || node),
    },
    newText: content,
  }
end

#mkdir(storage, relative_path) ⇒ Object



132
133
134
135
136
137
138
139
140
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 132

def mkdir(storage, relative_path)
  path = Pathname.new(relative_path).join("tmp").to_s
  # The LSP doesn't have a concept for directories, so what we
  # do is create a file and then delete it.
  #
  # It does the job :upside_down_smile:.
  create_file(storage, path)
  remove_file(storage, path)
end

#remove(node) ⇒ Object

Parameters:



57
58
59
60
61
62
63
64
65
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 57

def remove(node)
  edits(node) << {
    range: {
      start: { line: node.outer_markup_start_row, character: node.outer_markup_start_column },
      end: { line: node.outer_markup_end_row, character: node.outer_markup_end_column },
    },
    newText: '',
  }
end

#remove_file(storage, relative_path) ⇒ Object



127
128
129
130
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 127

def remove_file(storage, relative_path)
  uri = file_uri(storage.path(relative_path))
  @delete_files << delete_file_change(uri)
end

#remove_translation(file, path) ⇒ Object

Raises:

  • (ArgumentError)


149
150
151
152
153
154
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 149

def remove_translation(file, path)
  raise ArgumentError unless file.is_a?(JsonFile)
  hash = file.content
  SchemaHelper.delete(hash, path)
  @json_file_edits[file] = hash
end

#replace(node, content, character_range = nil) ⇒ Object



48
49
50
51
52
53
54
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 48

def replace(node, content, character_range = nil)
  position = character_range_position(node, character_range) if character_range
  edits(node) << {
    range: range(position || node),
    newText: content,
  }
end

#replace_inner_json(node, json, **pretty_json_opts) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 83

def replace_inner_json(node, json, **pretty_json_opts)
  # Kind of brittle alert: We're assuming that modifications are
  # made directly on the same json hash (e.g. schema). As such,
  # if this assumption is true, then it follows that the
  # "correct" JSON is the _last_ one that we defined.
  #
  # We're going to append those changes to the text edit when
  # we're done.
  #
  # We're doing this because no language client will accept
  # text modifications that occur on the same range. So we need
  # to dedup our JSON edits for the client to accept our change.
  #
  # What we're doing here is overwriting the json edit for a
  # node to the latest one that is called. If all the edits
  # occur on the same hash, this final hash will have all the
  # edits in it.
  @json_edits[node] = [json, pretty_json_opts]
end

#replace_inner_markup(node, content) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 67

def replace_inner_markup(node, content)
  edits(node) << {
    range: {
      start: {
        line: node.inner_markup_start_row,
        character: node.inner_markup_start_column,
      },
      end: {
        line: node.inner_markup_end_row,
        character: node.inner_markup_end_column,
      },
    },
    newText: content,
  }
end

#wrap(node, insert_before, insert_after) ⇒ Object



103
104
105
106
107
108
# File 'lib/theme_check/language_server/document_change_corrector.rb', line 103

def wrap(node, insert_before, insert_after)
  edits(node) << {
    range: range(node),
    newText: insert_before + node.markup + insert_after,
  }
end