platformos-check 0.0.1

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 (240) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +2 -0
  3. data/.gitignore +22 -0
  4. data/.rubocop.yml +555 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/CONTRIBUTING.md +209 -0
  8. data/Gemfile +33 -0
  9. data/Guardfile +7 -0
  10. data/LICENSE.md +10 -0
  11. data/Makefile +18 -0
  12. data/README.md +189 -0
  13. data/RELEASING.md +35 -0
  14. data/Rakefile +83 -0
  15. data/TROUBLESHOOTING.md +35 -0
  16. data/bin/platformos-check +29 -0
  17. data/bin/platformos-check-language-server +29 -0
  18. data/config/default.yml +98 -0
  19. data/config/nothing.yml +11 -0
  20. data/data/platformos_liquid/built_in_liquid_objects.json +66 -0
  21. data/data/platformos_liquid/deprecated_filters.json +22 -0
  22. data/data/platformos_liquid/documentation/filters.json +6 -0
  23. data/data/platformos_liquid/documentation/latest.json +2 -0
  24. data/data/platformos_liquid/documentation/objects.json +6 -0
  25. data/data/platformos_liquid/documentation/tags.json +6 -0
  26. data/docker/check.Dockerfile +3 -0
  27. data/docker/lsp.Dockerfile +21 -0
  28. data/docs/api/check.md +15 -0
  29. data/docs/api/html_check.md +46 -0
  30. data/docs/api/liquid_check.md +115 -0
  31. data/docs/api/yaml_check.md +19 -0
  32. data/docs/checks/TEMPLATE.md.erb +52 -0
  33. data/docs/checks/convert_include_to_render.md +48 -0
  34. data/docs/checks/deprecated_filter.md +30 -0
  35. data/docs/checks/html_parsing_error.md +50 -0
  36. data/docs/checks/img_lazy_loading.md +63 -0
  37. data/docs/checks/img_width_and_height.md +79 -0
  38. data/docs/checks/invalid_args.md +56 -0
  39. data/docs/checks/liquid_tag.md +65 -0
  40. data/docs/checks/missing_enable_comment.md +50 -0
  41. data/docs/checks/missing_template.md +65 -0
  42. data/docs/checks/parse_json_format.md +76 -0
  43. data/docs/checks/parser_blocking_javascript.md +97 -0
  44. data/docs/checks/required_layout_object.md +28 -0
  45. data/docs/checks/space_inside_braces.md +89 -0
  46. data/docs/checks/syntax_error.md +49 -0
  47. data/docs/checks/template_length.md +45 -0
  48. data/docs/checks/undefined_object.md +71 -0
  49. data/docs/checks/unknown_filter.md +46 -0
  50. data/docs/checks/unused_assign.md +63 -0
  51. data/docs/checks/unused_partial.md +32 -0
  52. data/docs/checks/valid_yaml.md +48 -0
  53. data/docs/flamegraph.svg +18488 -0
  54. data/docs/language_server/code-action-command-palette.png +0 -0
  55. data/docs/language_server/code-action-flow.png +0 -0
  56. data/docs/language_server/code-action-keyboard.png +0 -0
  57. data/docs/language_server/code-action-light-bulb.png +0 -0
  58. data/docs/language_server/code-action-problem.png +0 -0
  59. data/docs/language_server/code-action-quickfix.png +0 -0
  60. data/docs/language_server/how_to_correct_code_with_code_actions_and_execute_command.md +197 -0
  61. data/docs/preview.png +0 -0
  62. data/exe/platformos-check +6 -0
  63. data/exe/platformos-check-language-server +7 -0
  64. data/lib/platformos_check/analyzer.rb +178 -0
  65. data/lib/platformos_check/api_call_file.rb +9 -0
  66. data/lib/platformos_check/app.rb +138 -0
  67. data/lib/platformos_check/app_file.rb +89 -0
  68. data/lib/platformos_check/app_file_rewriter.rb +79 -0
  69. data/lib/platformos_check/asset_file.rb +34 -0
  70. data/lib/platformos_check/bug.rb +23 -0
  71. data/lib/platformos_check/check.rb +163 -0
  72. data/lib/platformos_check/checks/TEMPLATE.rb.erb +11 -0
  73. data/lib/platformos_check/checks/convert_include_to_render.rb +17 -0
  74. data/lib/platformos_check/checks/deprecated_filter.rb +123 -0
  75. data/lib/platformos_check/checks/html_parsing_error.rb +13 -0
  76. data/lib/platformos_check/checks/img_lazy_loading.rb +18 -0
  77. data/lib/platformos_check/checks/img_width_and_height.rb +46 -0
  78. data/lib/platformos_check/checks/invalid_args.rb +81 -0
  79. data/lib/platformos_check/checks/liquid_tag.rb +47 -0
  80. data/lib/platformos_check/checks/missing_enable_comment.rb +37 -0
  81. data/lib/platformos_check/checks/missing_template.rb +107 -0
  82. data/lib/platformos_check/checks/parse_json_format.rb +31 -0
  83. data/lib/platformos_check/checks/parser_blocking_javascript.rb +17 -0
  84. data/lib/platformos_check/checks/required_layout_object.rb +41 -0
  85. data/lib/platformos_check/checks/space_inside_braces.rb +150 -0
  86. data/lib/platformos_check/checks/syntax_error.rb +31 -0
  87. data/lib/platformos_check/checks/template_length.rb +20 -0
  88. data/lib/platformos_check/checks/undefined_object.rb +206 -0
  89. data/lib/platformos_check/checks/unknown_filter.rb +27 -0
  90. data/lib/platformos_check/checks/unused_assign.rb +101 -0
  91. data/lib/platformos_check/checks/unused_partial.rb +93 -0
  92. data/lib/platformos_check/checks/valid_yaml.rb +16 -0
  93. data/lib/platformos_check/checks.rb +73 -0
  94. data/lib/platformos_check/checks_tracking.rb +9 -0
  95. data/lib/platformos_check/cli.rb +239 -0
  96. data/lib/platformos_check/config.rb +219 -0
  97. data/lib/platformos_check/config_file.rb +6 -0
  98. data/lib/platformos_check/corrector.rb +68 -0
  99. data/lib/platformos_check/disabled_check.rb +44 -0
  100. data/lib/platformos_check/disabled_checks.rb +96 -0
  101. data/lib/platformos_check/email_file.rb +9 -0
  102. data/lib/platformos_check/exceptions.rb +36 -0
  103. data/lib/platformos_check/file_system_storage.rb +93 -0
  104. data/lib/platformos_check/graphql_file.rb +68 -0
  105. data/lib/platformos_check/html_check.rb +8 -0
  106. data/lib/platformos_check/html_node.rb +210 -0
  107. data/lib/platformos_check/html_visitor.rb +36 -0
  108. data/lib/platformos_check/in_memory_storage.rb +68 -0
  109. data/lib/platformos_check/json_file.rb +57 -0
  110. data/lib/platformos_check/json_helper.rb +73 -0
  111. data/lib/platformos_check/json_helpers.rb +24 -0
  112. data/lib/platformos_check/json_printer.rb +32 -0
  113. data/lib/platformos_check/language_server/bridge.rb +167 -0
  114. data/lib/platformos_check/language_server/channel.rb +69 -0
  115. data/lib/platformos_check/language_server/client_capabilities.rb +27 -0
  116. data/lib/platformos_check/language_server/code_action_engine.rb +32 -0
  117. data/lib/platformos_check/language_server/code_action_provider.rb +41 -0
  118. data/lib/platformos_check/language_server/code_action_providers/quickfix_code_action_provider.rb +85 -0
  119. data/lib/platformos_check/language_server/code_action_providers/source_fix_all_code_action_provider.rb +41 -0
  120. data/lib/platformos_check/language_server/completion_context.rb +52 -0
  121. data/lib/platformos_check/language_server/completion_engine.rb +32 -0
  122. data/lib/platformos_check/language_server/completion_helper.rb +26 -0
  123. data/lib/platformos_check/language_server/completion_provider.rb +53 -0
  124. data/lib/platformos_check/language_server/completion_providers/assignments_completion_provider.rb +40 -0
  125. data/lib/platformos_check/language_server/completion_providers/filter_completion_provider.rb +102 -0
  126. data/lib/platformos_check/language_server/completion_providers/object_attribute_completion_provider.rb +48 -0
  127. data/lib/platformos_check/language_server/completion_providers/object_completion_provider.rb +38 -0
  128. data/lib/platformos_check/language_server/completion_providers/render_snippet_completion_provider.rb +50 -0
  129. data/lib/platformos_check/language_server/completion_providers/tag_completion_provider.rb +41 -0
  130. data/lib/platformos_check/language_server/configuration.rb +89 -0
  131. data/lib/platformos_check/language_server/constants.rb +29 -0
  132. data/lib/platformos_check/language_server/diagnostic.rb +129 -0
  133. data/lib/platformos_check/language_server/diagnostics_engine.rb +131 -0
  134. data/lib/platformos_check/language_server/diagnostics_manager.rb +184 -0
  135. data/lib/platformos_check/language_server/document_change_corrector.rb +271 -0
  136. data/lib/platformos_check/language_server/document_link_engine.rb +21 -0
  137. data/lib/platformos_check/language_server/document_link_provider.rb +71 -0
  138. data/lib/platformos_check/language_server/document_link_providers/asset_document_link_provider.rb +11 -0
  139. data/lib/platformos_check/language_server/document_link_providers/include_document_link_provider.rb +11 -0
  140. data/lib/platformos_check/language_server/document_link_providers/render_document_link_provider.rb +11 -0
  141. data/lib/platformos_check/language_server/document_link_providers/section_document_link_provider.rb +11 -0
  142. data/lib/platformos_check/language_server/execute_command_engine.rb +19 -0
  143. data/lib/platformos_check/language_server/execute_command_provider.rb +30 -0
  144. data/lib/platformos_check/language_server/execute_command_providers/correction_execute_command_provider.rb +48 -0
  145. data/lib/platformos_check/language_server/execute_command_providers/run_checks_execute_command_provider.rb +28 -0
  146. data/lib/platformos_check/language_server/handler.rb +310 -0
  147. data/lib/platformos_check/language_server/hover_engine.rb +32 -0
  148. data/lib/platformos_check/language_server/hover_provider.rb +53 -0
  149. data/lib/platformos_check/language_server/hover_providers/filter_hover_provider.rb +113 -0
  150. data/lib/platformos_check/language_server/io_messenger.rb +109 -0
  151. data/lib/platformos_check/language_server/messenger.rb +27 -0
  152. data/lib/platformos_check/language_server/protocol.rb +55 -0
  153. data/lib/platformos_check/language_server/server.rb +188 -0
  154. data/lib/platformos_check/language_server/tokens.rb +55 -0
  155. data/lib/platformos_check/language_server/type_helper.rb +22 -0
  156. data/lib/platformos_check/language_server/uri_helper.rb +39 -0
  157. data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/node_handler.rb +87 -0
  158. data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/scope.rb +60 -0
  159. data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/scope_visitor.rb +44 -0
  160. data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder.rb +76 -0
  161. data/lib/platformos_check/language_server/variable_lookup_finder/constants.rb +44 -0
  162. data/lib/platformos_check/language_server/variable_lookup_finder/liquid_fixer.rb +103 -0
  163. data/lib/platformos_check/language_server/variable_lookup_finder/potential_lookup.rb +10 -0
  164. data/lib/platformos_check/language_server/variable_lookup_finder/tolerant_parser.rb +94 -0
  165. data/lib/platformos_check/language_server/variable_lookup_finder.rb +262 -0
  166. data/lib/platformos_check/language_server/variable_lookup_traverser.rb +70 -0
  167. data/lib/platformos_check/language_server/versioned_in_memory_storage.rb +84 -0
  168. data/lib/platformos_check/language_server.rb +71 -0
  169. data/lib/platformos_check/layout_file.rb +15 -0
  170. data/lib/platformos_check/liquid_check.rb +10 -0
  171. data/lib/platformos_check/liquid_file.rb +102 -0
  172. data/lib/platformos_check/liquid_node.rb +570 -0
  173. data/lib/platformos_check/liquid_visitor.rb +39 -0
  174. data/lib/platformos_check/migration_file.rb +9 -0
  175. data/lib/platformos_check/node.rb +53 -0
  176. data/lib/platformos_check/offense.rb +228 -0
  177. data/lib/platformos_check/page_file.rb +9 -0
  178. data/lib/platformos_check/parsing_helpers.rb +21 -0
  179. data/lib/platformos_check/partial_file.rb +15 -0
  180. data/lib/platformos_check/platformos_liquid/deprecated_filter.rb +31 -0
  181. data/lib/platformos_check/platformos_liquid/documentation/markdown_template.rb +51 -0
  182. data/lib/platformos_check/platformos_liquid/documentation.rb +45 -0
  183. data/lib/platformos_check/platformos_liquid/filter.rb +19 -0
  184. data/lib/platformos_check/platformos_liquid/object.rb +15 -0
  185. data/lib/platformos_check/platformos_liquid/source_index/base_entry.rb +66 -0
  186. data/lib/platformos_check/platformos_liquid/source_index/base_state.rb +23 -0
  187. data/lib/platformos_check/platformos_liquid/source_index/filter_entry.rb +26 -0
  188. data/lib/platformos_check/platformos_liquid/source_index/filter_state.rb +11 -0
  189. data/lib/platformos_check/platformos_liquid/source_index/object_entry.rb +20 -0
  190. data/lib/platformos_check/platformos_liquid/source_index/object_state.rb +11 -0
  191. data/lib/platformos_check/platformos_liquid/source_index/parameter_entry.rb +25 -0
  192. data/lib/platformos_check/platformos_liquid/source_index/property_entry.rb +21 -0
  193. data/lib/platformos_check/platformos_liquid/source_index/return_type_entry.rb +41 -0
  194. data/lib/platformos_check/platformos_liquid/source_index/tag_entry.rb +24 -0
  195. data/lib/platformos_check/platformos_liquid/source_index/tag_state.rb +11 -0
  196. data/lib/platformos_check/platformos_liquid/source_index.rb +79 -0
  197. data/lib/platformos_check/platformos_liquid/source_manager.rb +116 -0
  198. data/lib/platformos_check/platformos_liquid/tag.rb +59 -0
  199. data/lib/platformos_check/platformos_liquid.rb +21 -0
  200. data/lib/platformos_check/position.rb +180 -0
  201. data/lib/platformos_check/position_helper.rb +57 -0
  202. data/lib/platformos_check/printer.rb +87 -0
  203. data/lib/platformos_check/regex_helpers.rb +21 -0
  204. data/lib/platformos_check/releaser.rb +43 -0
  205. data/lib/platformos_check/schema_file.rb +6 -0
  206. data/lib/platformos_check/sms_file.rb +9 -0
  207. data/lib/platformos_check/storage.rb +29 -0
  208. data/lib/platformos_check/string_helpers.rb +48 -0
  209. data/lib/platformos_check/tags/background.rb +67 -0
  210. data/lib/platformos_check/tags/base.rb +14 -0
  211. data/lib/platformos_check/tags/base_block.rb +14 -0
  212. data/lib/platformos_check/tags/base_tag_methods.rb +59 -0
  213. data/lib/platformos_check/tags/cache.rb +13 -0
  214. data/lib/platformos_check/tags/export.rb +30 -0
  215. data/lib/platformos_check/tags/form.rb +19 -0
  216. data/lib/platformos_check/tags/function.rb +58 -0
  217. data/lib/platformos_check/tags/graphql.rb +70 -0
  218. data/lib/platformos_check/tags/hash_assign.rb +75 -0
  219. data/lib/platformos_check/tags/log.rb +15 -0
  220. data/lib/platformos_check/tags/parse_json.rb +24 -0
  221. data/lib/platformos_check/tags/print.rb +20 -0
  222. data/lib/platformos_check/tags/redirect_to.rb +15 -0
  223. data/lib/platformos_check/tags/render.rb +60 -0
  224. data/lib/platformos_check/tags/response_headers.rb +20 -0
  225. data/lib/platformos_check/tags/response_status.rb +20 -0
  226. data/lib/platformos_check/tags/return.rb +20 -0
  227. data/lib/platformos_check/tags/session.rb +27 -0
  228. data/lib/platformos_check/tags/sign_in.rb +27 -0
  229. data/lib/platformos_check/tags/spam_protection.rb +15 -0
  230. data/lib/platformos_check/tags/theme_render.rb +58 -0
  231. data/lib/platformos_check/tags/try.rb +59 -0
  232. data/lib/platformos_check/tags.rb +65 -0
  233. data/lib/platformos_check/translation_file.rb +6 -0
  234. data/lib/platformos_check/user_schema_file.rb +6 -0
  235. data/lib/platformos_check/version.rb +5 -0
  236. data/lib/platformos_check/yaml_check.rb +11 -0
  237. data/lib/platformos_check/yaml_file.rb +57 -0
  238. data/lib/platformos_check.rb +106 -0
  239. data/platformos-check.gemspec +34 -0
  240. metadata +329 -0
@@ -0,0 +1,271 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class DocumentChangeCorrector
6
+ include URIHelper
7
+ include JsonHelpers
8
+
9
+ def initialize
10
+ @json_edits = {}
11
+ @json_file_edits = {}
12
+ @text_document_edits = {}
13
+ @create_files = []
14
+ @rename_files = []
15
+ @delete_files = []
16
+ end
17
+
18
+ def document_changes
19
+ apply_json_edits
20
+ apply_json_file_edits
21
+ @create_files + @rename_files + @text_document_edits.values + @delete_files
22
+ end
23
+
24
+ # @param node [Node]
25
+ def insert_before(node, content, character_range = nil)
26
+ position = character_range_position(node, character_range) if character_range
27
+ edits(node) << {
28
+ range: {
29
+ start: start_location(position || node),
30
+ end: start_location(position || node)
31
+ },
32
+ newText: content
33
+ }
34
+ end
35
+
36
+ # @param node [Node]
37
+ def insert_after(node, content, character_range = nil)
38
+ position = character_range_position(node, character_range) if character_range
39
+ edits(node) << {
40
+ range: {
41
+ start: end_location(position || node),
42
+ end: end_location(position || node)
43
+ },
44
+ newText: content
45
+ }
46
+ end
47
+
48
+ def replace(node, content, character_range = nil)
49
+ position = character_range_position(node, character_range) if character_range
50
+ edits(node) << {
51
+ range: range(position || node),
52
+ newText: content
53
+ }
54
+ end
55
+
56
+ # @param node [LiquidNode]
57
+ def remove(node)
58
+ edits(node) << {
59
+ range: {
60
+ start: { line: node.outer_markup_start_row, character: node.outer_markup_start_column },
61
+ end: { line: node.outer_markup_end_row, character: node.outer_markup_end_column }
62
+ },
63
+ newText: ''
64
+ }
65
+ end
66
+
67
+ def replace_inner_markup(node, content)
68
+ edits(node) << {
69
+ range: {
70
+ start: {
71
+ line: node.inner_markup_start_row,
72
+ character: node.inner_markup_start_column
73
+ },
74
+ end: {
75
+ line: node.inner_markup_end_row,
76
+ character: node.inner_markup_end_column
77
+ }
78
+ },
79
+ newText: content
80
+ }
81
+ end
82
+
83
+ def replace_inner_json(node, json, **pretty_json_opts)
84
+ # Kind of brittle alert: We're assuming that modifications are
85
+ # made directly on the same json hash (e.g. schema). As such,
86
+ # if this assumption is true, then it follows that the
87
+ # "correct" JSON is the _last_ one that we defined.
88
+ #
89
+ # We're going to append those changes to the text edit when
90
+ # we're done.
91
+ #
92
+ # We're doing this because no language client will accept
93
+ # text modifications that occur on the same range. So we need
94
+ # to dedup our JSON edits for the client to accept our change.
95
+ #
96
+ # What we're doing here is overwriting the json edit for a
97
+ # node to the latest one that is called. If all the edits
98
+ # occur on the same hash, this final hash will have all the
99
+ # edits in it.
100
+ @json_edits[node] = [json, pretty_json_opts]
101
+ end
102
+
103
+ def wrap(node, insert_before, insert_after)
104
+ edits(node) << {
105
+ range: range(node),
106
+ newText: insert_before + node.markup + insert_after
107
+ }
108
+ end
109
+
110
+ def create_file(storage, relative_path, contents = nil, overwrite: false)
111
+ uri = file_uri(storage.path(relative_path))
112
+ @create_files << create_file_change(uri, overwrite)
113
+ return if contents.nil?
114
+
115
+ text_document = { uri:, version: nil }
116
+ @text_document_edits[text_document] = {
117
+ textDocument: text_document,
118
+ edits: [{
119
+ range: {
120
+ start: { line: 0, character: 0 },
121
+ end: { line: 0, character: 0 }
122
+ },
123
+ newText: contents
124
+ }]
125
+ }
126
+ end
127
+
128
+ def remove_file(storage, relative_path)
129
+ uri = file_uri(storage.path(relative_path))
130
+ @delete_files << delete_file_change(uri)
131
+ end
132
+
133
+ def mkdir(storage, relative_path)
134
+ path = Pathname.new(relative_path).join("tmp").to_s
135
+ # The LSP doesn't have a concept for directories, so what we
136
+ # do is create a file and then delete it.
137
+ #
138
+ # It does the job :upside_down_smile:.
139
+ create_file(storage, path)
140
+ remove_file(storage, path)
141
+ end
142
+
143
+ def add_translation(file, path, value)
144
+ raise ArgumentError unless file.is_a?(JsonFile)
145
+
146
+ hash = file.content
147
+ JsonHelper.set(hash, path, value)
148
+ @json_file_edits[file] = hash
149
+ end
150
+
151
+ def remove_translation(file, path)
152
+ raise ArgumentError unless file.is_a?(JsonFile)
153
+
154
+ hash = file.content
155
+ JsonHelper.delete(hash, path)
156
+ @json_file_edits[file] = hash
157
+ end
158
+
159
+ private
160
+
161
+ def apply_json_edits
162
+ @json_edits.each do |node, (json, pretty_json_opts)|
163
+ replace_inner_markup(node, pretty_json(json, **pretty_json_opts))
164
+ end
165
+ end
166
+
167
+ def apply_json_file_edits
168
+ @json_file_edits.each do |file, hash|
169
+ replace_entire_file(file, JSON.pretty_generate(hash))
170
+ end
171
+ end
172
+
173
+ def replace_entire_file(file, contents)
174
+ text_document = to_text_document(file)
175
+ position = PlatformosCheck::StrictPosition.new(file.source, file.source, 0)
176
+ @text_document_edits[text_document] = {
177
+ textDocument: text_document,
178
+ edits: [{
179
+ range: {
180
+ start: { line: 0, character: 0 },
181
+ end: { line: position.end_row, character: position.end_column }
182
+ },
183
+ newText: contents
184
+ }]
185
+ }
186
+ end
187
+
188
+ # @param node [Node]
189
+ def text_document_edit(node)
190
+ text_document = to_text_document(node)
191
+ @text_document_edits[text_document] ||= {
192
+ textDocument: text_document,
193
+ edits: []
194
+ }
195
+ end
196
+
197
+ def create_file_change(uri, overwrite = false)
198
+ change = {}
199
+ change[:kind] = 'create'
200
+ change[:uri] = uri
201
+ change[:options] = { overwrite: } if overwrite
202
+ change
203
+ end
204
+
205
+ def delete_file_change(uri)
206
+ {
207
+ kind: 'delete',
208
+ uri:
209
+ }
210
+ end
211
+
212
+ def edits(node)
213
+ text_document_edit(node)[:edits]
214
+ end
215
+
216
+ def to_text_document(thing)
217
+ case thing
218
+ when Node
219
+ {
220
+ uri: file_uri(thing.app_file&.path),
221
+ version: thing.app_file&.version
222
+ }
223
+ when AppFile
224
+ {
225
+ uri: file_uri(thing.path),
226
+ version: thing.version
227
+ }
228
+ else
229
+ raise ArgumentError
230
+ end
231
+ end
232
+
233
+ def absolute_path(node)
234
+ node.app_file&.path
235
+ end
236
+
237
+ def character_range_position(node, character_range)
238
+ return unless character_range
239
+
240
+ source = node.app_file.source
241
+ StrictPosition.new(
242
+ source[character_range],
243
+ source,
244
+ character_range.begin
245
+ )
246
+ end
247
+
248
+ # @param node [PlatformosCheck::Node]
249
+ def range(node)
250
+ {
251
+ start: start_location(node),
252
+ end: end_location(node)
253
+ }
254
+ end
255
+
256
+ def start_location(node)
257
+ {
258
+ line: node.start_row,
259
+ character: node.start_column
260
+ }
261
+ end
262
+
263
+ def end_location(node)
264
+ {
265
+ line: node.end_row,
266
+ character: node.end_column
267
+ }
268
+ end
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class DocumentLinkEngine
6
+ def initialize(storage)
7
+ @storage = storage
8
+ @providers = DocumentLinkProvider.all.map { |x| x.new(storage) }
9
+ end
10
+
11
+ def document_links(relative_path)
12
+ buffer = @storage.read(relative_path)
13
+ return [] unless buffer
14
+
15
+ @providers.flat_map do |p|
16
+ p.document_links(buffer)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class DocumentLinkProvider
6
+ include RegexHelpers
7
+ include PositionHelper
8
+ include URIHelper
9
+
10
+ class << self
11
+ attr_accessor :partial_regexp, :destination_directory, :destination_postfix
12
+
13
+ def all
14
+ @all ||= []
15
+ end
16
+
17
+ def inherited(subclass)
18
+ all << subclass
19
+ end
20
+ end
21
+
22
+ def initialize(storage = InMemoryStorage.new)
23
+ @storage = storage
24
+ end
25
+
26
+ def partial_regexp
27
+ self.class.partial_regexp
28
+ end
29
+
30
+ def destination_directory
31
+ self.class.destination_directory
32
+ end
33
+
34
+ def destination_postfix
35
+ self.class.destination_postfix
36
+ end
37
+
38
+ def document_links(buffer)
39
+ matches(buffer, partial_regexp).map do |match|
40
+ start_row, start_column = from_index_to_row_column(
41
+ buffer,
42
+ match.begin(:partial)
43
+ )
44
+
45
+ end_row, end_column = from_index_to_row_column(
46
+ buffer,
47
+ match.end(:partial)
48
+ )
49
+
50
+ {
51
+ target: file_link(match[:partial]),
52
+ range: {
53
+ start: {
54
+ line: start_row,
55
+ character: start_column
56
+ },
57
+ end: {
58
+ line: end_row,
59
+ character: end_column
60
+ }
61
+ }
62
+ }
63
+ end
64
+ end
65
+
66
+ def file_link(partial)
67
+ file_uri(@storage.path(destination_directory + '/' + partial + destination_postfix))
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class AssetDocumentLinkProvider < DocumentLinkProvider
6
+ @partial_regexp = ASSET_INCLUDE
7
+ @destination_directory = "assets"
8
+ @destination_postfix = ""
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class IncludeDocumentLinkProvider < DocumentLinkProvider
6
+ @partial_regexp = PARTIAL_INCLUDE
7
+ @destination_directory = "snippets"
8
+ @destination_postfix = ".liquid"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class RenderDocumentLinkProvider < DocumentLinkProvider
6
+ @partial_regexp = PARTIAL_RENDER
7
+ @destination_directory = "snippets"
8
+ @destination_postfix = ".liquid"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class SectionDocumentLinkProvider < DocumentLinkProvider
6
+ @partial_regexp = PARTIAL_SECTION
7
+ @destination_directory = "sections"
8
+ @destination_postfix = ".liquid"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class ExecuteCommandEngine
6
+ def initialize
7
+ @providers = {}
8
+ end
9
+
10
+ def <<(provider)
11
+ @providers[provider.command] = provider
12
+ end
13
+
14
+ def execute(command, arguments)
15
+ @providers[command].execute(arguments)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class ExecuteCommandProvider
6
+ class << self
7
+ def all
8
+ @all ||= []
9
+ end
10
+
11
+ def inherited(subclass)
12
+ all << subclass
13
+ end
14
+
15
+ def command(cmd = nil)
16
+ @command = cmd unless cmd.nil?
17
+ @command
18
+ end
19
+ end
20
+
21
+ def execute(arguments)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def command
26
+ self.class.command
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class CorrectionExecuteCommandProvider < ExecuteCommandProvider
6
+ include URIHelper
7
+
8
+ command "correction"
9
+
10
+ attr_reader :storage, :bridge, :diagnostics_manager
11
+
12
+ def initialize(storage, bridge, diagnostics_manager)
13
+ @storage = storage
14
+ @bridge = bridge
15
+ @diagnostics_manager = diagnostics_manager
16
+ end
17
+
18
+ # The arguments passed to this method are the ones forwarded
19
+ # from the selected CodeAction by the client.
20
+ #
21
+ # @param diagnostic_hashes [Array] - of diagnostics
22
+ def execute(diagnostic_hashes)
23
+ # attempt to apply the document changes
24
+ workspace_edit = diagnostics_manager.workspace_edit(diagnostic_hashes)
25
+ result = bridge.send_request('workspace/applyEdit', {
26
+ label: 'PlatformOS Check correction',
27
+ edit: workspace_edit
28
+ })
29
+
30
+ # Bail if unable to apply changes
31
+ return unless result[:applied]
32
+
33
+ # Clean up internal representation of fixed diagnostics
34
+ diagnostics_update = diagnostics_manager.delete_applied(diagnostic_hashes)
35
+
36
+ # Send updated diagnostics to client
37
+ diagnostics_update
38
+ .map do |relative_path, diagnostics|
39
+ bridge.send_notification('textDocument/publishDiagnostics', {
40
+ uri: file_uri(storage.path(relative_path)),
41
+ diagnostics: diagnostics.map(&:to_h)
42
+ })
43
+ storage.path(relative_path)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ module LanguageServer
5
+ class RunChecksExecuteCommandProvider < ExecuteCommandProvider
6
+ include URIHelper
7
+
8
+ command "runChecks"
9
+
10
+ def initialize(diagnostics_engine, storage, linter_config, language_server_config)
11
+ @diagnostics_engine = diagnostics_engine
12
+ @storage = storage
13
+ @linter_config = linter_config
14
+ @language_server_config = language_server_config
15
+ end
16
+
17
+ def execute(_args)
18
+ @diagnostics_engine.analyze_and_send_offenses(
19
+ @storage.opened_files.map { |relative_path| @storage.path(relative_path) },
20
+ @linter_config,
21
+ only_single_file: @language_server_config.only_single_file?,
22
+ force: true
23
+ )
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end