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.
- checksums.yaml +7 -0
- data/.dockerignore +2 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +555 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +209 -0
- data/Gemfile +33 -0
- data/Guardfile +7 -0
- data/LICENSE.md +10 -0
- data/Makefile +18 -0
- data/README.md +189 -0
- data/RELEASING.md +35 -0
- data/Rakefile +83 -0
- data/TROUBLESHOOTING.md +35 -0
- data/bin/platformos-check +29 -0
- data/bin/platformos-check-language-server +29 -0
- data/config/default.yml +98 -0
- data/config/nothing.yml +11 -0
- data/data/platformos_liquid/built_in_liquid_objects.json +66 -0
- data/data/platformos_liquid/deprecated_filters.json +22 -0
- data/data/platformos_liquid/documentation/filters.json +6 -0
- data/data/platformos_liquid/documentation/latest.json +2 -0
- data/data/platformos_liquid/documentation/objects.json +6 -0
- data/data/platformos_liquid/documentation/tags.json +6 -0
- data/docker/check.Dockerfile +3 -0
- data/docker/lsp.Dockerfile +21 -0
- data/docs/api/check.md +15 -0
- data/docs/api/html_check.md +46 -0
- data/docs/api/liquid_check.md +115 -0
- data/docs/api/yaml_check.md +19 -0
- data/docs/checks/TEMPLATE.md.erb +52 -0
- data/docs/checks/convert_include_to_render.md +48 -0
- data/docs/checks/deprecated_filter.md +30 -0
- data/docs/checks/html_parsing_error.md +50 -0
- data/docs/checks/img_lazy_loading.md +63 -0
- data/docs/checks/img_width_and_height.md +79 -0
- data/docs/checks/invalid_args.md +56 -0
- data/docs/checks/liquid_tag.md +65 -0
- data/docs/checks/missing_enable_comment.md +50 -0
- data/docs/checks/missing_template.md +65 -0
- data/docs/checks/parse_json_format.md +76 -0
- data/docs/checks/parser_blocking_javascript.md +97 -0
- data/docs/checks/required_layout_object.md +28 -0
- data/docs/checks/space_inside_braces.md +89 -0
- data/docs/checks/syntax_error.md +49 -0
- data/docs/checks/template_length.md +45 -0
- data/docs/checks/undefined_object.md +71 -0
- data/docs/checks/unknown_filter.md +46 -0
- data/docs/checks/unused_assign.md +63 -0
- data/docs/checks/unused_partial.md +32 -0
- data/docs/checks/valid_yaml.md +48 -0
- data/docs/flamegraph.svg +18488 -0
- data/docs/language_server/code-action-command-palette.png +0 -0
- data/docs/language_server/code-action-flow.png +0 -0
- data/docs/language_server/code-action-keyboard.png +0 -0
- data/docs/language_server/code-action-light-bulb.png +0 -0
- data/docs/language_server/code-action-problem.png +0 -0
- data/docs/language_server/code-action-quickfix.png +0 -0
- data/docs/language_server/how_to_correct_code_with_code_actions_and_execute_command.md +197 -0
- data/docs/preview.png +0 -0
- data/exe/platformos-check +6 -0
- data/exe/platformos-check-language-server +7 -0
- data/lib/platformos_check/analyzer.rb +178 -0
- data/lib/platformos_check/api_call_file.rb +9 -0
- data/lib/platformos_check/app.rb +138 -0
- data/lib/platformos_check/app_file.rb +89 -0
- data/lib/platformos_check/app_file_rewriter.rb +79 -0
- data/lib/platformos_check/asset_file.rb +34 -0
- data/lib/platformos_check/bug.rb +23 -0
- data/lib/platformos_check/check.rb +163 -0
- data/lib/platformos_check/checks/TEMPLATE.rb.erb +11 -0
- data/lib/platformos_check/checks/convert_include_to_render.rb +17 -0
- data/lib/platformos_check/checks/deprecated_filter.rb +123 -0
- data/lib/platformos_check/checks/html_parsing_error.rb +13 -0
- data/lib/platformos_check/checks/img_lazy_loading.rb +18 -0
- data/lib/platformos_check/checks/img_width_and_height.rb +46 -0
- data/lib/platformos_check/checks/invalid_args.rb +81 -0
- data/lib/platformos_check/checks/liquid_tag.rb +47 -0
- data/lib/platformos_check/checks/missing_enable_comment.rb +37 -0
- data/lib/platformos_check/checks/missing_template.rb +107 -0
- data/lib/platformos_check/checks/parse_json_format.rb +31 -0
- data/lib/platformos_check/checks/parser_blocking_javascript.rb +17 -0
- data/lib/platformos_check/checks/required_layout_object.rb +41 -0
- data/lib/platformos_check/checks/space_inside_braces.rb +150 -0
- data/lib/platformos_check/checks/syntax_error.rb +31 -0
- data/lib/platformos_check/checks/template_length.rb +20 -0
- data/lib/platformos_check/checks/undefined_object.rb +206 -0
- data/lib/platformos_check/checks/unknown_filter.rb +27 -0
- data/lib/platformos_check/checks/unused_assign.rb +101 -0
- data/lib/platformos_check/checks/unused_partial.rb +93 -0
- data/lib/platformos_check/checks/valid_yaml.rb +16 -0
- data/lib/platformos_check/checks.rb +73 -0
- data/lib/platformos_check/checks_tracking.rb +9 -0
- data/lib/platformos_check/cli.rb +239 -0
- data/lib/platformos_check/config.rb +219 -0
- data/lib/platformos_check/config_file.rb +6 -0
- data/lib/platformos_check/corrector.rb +68 -0
- data/lib/platformos_check/disabled_check.rb +44 -0
- data/lib/platformos_check/disabled_checks.rb +96 -0
- data/lib/platformos_check/email_file.rb +9 -0
- data/lib/platformos_check/exceptions.rb +36 -0
- data/lib/platformos_check/file_system_storage.rb +93 -0
- data/lib/platformos_check/graphql_file.rb +68 -0
- data/lib/platformos_check/html_check.rb +8 -0
- data/lib/platformos_check/html_node.rb +210 -0
- data/lib/platformos_check/html_visitor.rb +36 -0
- data/lib/platformos_check/in_memory_storage.rb +68 -0
- data/lib/platformos_check/json_file.rb +57 -0
- data/lib/platformos_check/json_helper.rb +73 -0
- data/lib/platformos_check/json_helpers.rb +24 -0
- data/lib/platformos_check/json_printer.rb +32 -0
- data/lib/platformos_check/language_server/bridge.rb +167 -0
- data/lib/platformos_check/language_server/channel.rb +69 -0
- data/lib/platformos_check/language_server/client_capabilities.rb +27 -0
- data/lib/platformos_check/language_server/code_action_engine.rb +32 -0
- data/lib/platformos_check/language_server/code_action_provider.rb +41 -0
- data/lib/platformos_check/language_server/code_action_providers/quickfix_code_action_provider.rb +85 -0
- data/lib/platformos_check/language_server/code_action_providers/source_fix_all_code_action_provider.rb +41 -0
- data/lib/platformos_check/language_server/completion_context.rb +52 -0
- data/lib/platformos_check/language_server/completion_engine.rb +32 -0
- data/lib/platformos_check/language_server/completion_helper.rb +26 -0
- data/lib/platformos_check/language_server/completion_provider.rb +53 -0
- data/lib/platformos_check/language_server/completion_providers/assignments_completion_provider.rb +40 -0
- data/lib/platformos_check/language_server/completion_providers/filter_completion_provider.rb +102 -0
- data/lib/platformos_check/language_server/completion_providers/object_attribute_completion_provider.rb +48 -0
- data/lib/platformos_check/language_server/completion_providers/object_completion_provider.rb +38 -0
- data/lib/platformos_check/language_server/completion_providers/render_snippet_completion_provider.rb +50 -0
- data/lib/platformos_check/language_server/completion_providers/tag_completion_provider.rb +41 -0
- data/lib/platformos_check/language_server/configuration.rb +89 -0
- data/lib/platformos_check/language_server/constants.rb +29 -0
- data/lib/platformos_check/language_server/diagnostic.rb +129 -0
- data/lib/platformos_check/language_server/diagnostics_engine.rb +131 -0
- data/lib/platformos_check/language_server/diagnostics_manager.rb +184 -0
- data/lib/platformos_check/language_server/document_change_corrector.rb +271 -0
- data/lib/platformos_check/language_server/document_link_engine.rb +21 -0
- data/lib/platformos_check/language_server/document_link_provider.rb +71 -0
- data/lib/platformos_check/language_server/document_link_providers/asset_document_link_provider.rb +11 -0
- data/lib/platformos_check/language_server/document_link_providers/include_document_link_provider.rb +11 -0
- data/lib/platformos_check/language_server/document_link_providers/render_document_link_provider.rb +11 -0
- data/lib/platformos_check/language_server/document_link_providers/section_document_link_provider.rb +11 -0
- data/lib/platformos_check/language_server/execute_command_engine.rb +19 -0
- data/lib/platformos_check/language_server/execute_command_provider.rb +30 -0
- data/lib/platformos_check/language_server/execute_command_providers/correction_execute_command_provider.rb +48 -0
- data/lib/platformos_check/language_server/execute_command_providers/run_checks_execute_command_provider.rb +28 -0
- data/lib/platformos_check/language_server/handler.rb +310 -0
- data/lib/platformos_check/language_server/hover_engine.rb +32 -0
- data/lib/platformos_check/language_server/hover_provider.rb +53 -0
- data/lib/platformos_check/language_server/hover_providers/filter_hover_provider.rb +113 -0
- data/lib/platformos_check/language_server/io_messenger.rb +109 -0
- data/lib/platformos_check/language_server/messenger.rb +27 -0
- data/lib/platformos_check/language_server/protocol.rb +55 -0
- data/lib/platformos_check/language_server/server.rb +188 -0
- data/lib/platformos_check/language_server/tokens.rb +55 -0
- data/lib/platformos_check/language_server/type_helper.rb +22 -0
- data/lib/platformos_check/language_server/uri_helper.rb +39 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/node_handler.rb +87 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/scope.rb +60 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder/scope_visitor.rb +44 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/assignments_finder.rb +76 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/constants.rb +44 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/liquid_fixer.rb +103 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/potential_lookup.rb +10 -0
- data/lib/platformos_check/language_server/variable_lookup_finder/tolerant_parser.rb +94 -0
- data/lib/platformos_check/language_server/variable_lookup_finder.rb +262 -0
- data/lib/platformos_check/language_server/variable_lookup_traverser.rb +70 -0
- data/lib/platformos_check/language_server/versioned_in_memory_storage.rb +84 -0
- data/lib/platformos_check/language_server.rb +71 -0
- data/lib/platformos_check/layout_file.rb +15 -0
- data/lib/platformos_check/liquid_check.rb +10 -0
- data/lib/platformos_check/liquid_file.rb +102 -0
- data/lib/platformos_check/liquid_node.rb +570 -0
- data/lib/platformos_check/liquid_visitor.rb +39 -0
- data/lib/platformos_check/migration_file.rb +9 -0
- data/lib/platformos_check/node.rb +53 -0
- data/lib/platformos_check/offense.rb +228 -0
- data/lib/platformos_check/page_file.rb +9 -0
- data/lib/platformos_check/parsing_helpers.rb +21 -0
- data/lib/platformos_check/partial_file.rb +15 -0
- data/lib/platformos_check/platformos_liquid/deprecated_filter.rb +31 -0
- data/lib/platformos_check/platformos_liquid/documentation/markdown_template.rb +51 -0
- data/lib/platformos_check/platformos_liquid/documentation.rb +45 -0
- data/lib/platformos_check/platformos_liquid/filter.rb +19 -0
- data/lib/platformos_check/platformos_liquid/object.rb +15 -0
- data/lib/platformos_check/platformos_liquid/source_index/base_entry.rb +66 -0
- data/lib/platformos_check/platformos_liquid/source_index/base_state.rb +23 -0
- data/lib/platformos_check/platformos_liquid/source_index/filter_entry.rb +26 -0
- data/lib/platformos_check/platformos_liquid/source_index/filter_state.rb +11 -0
- data/lib/platformos_check/platformos_liquid/source_index/object_entry.rb +20 -0
- data/lib/platformos_check/platformos_liquid/source_index/object_state.rb +11 -0
- data/lib/platformos_check/platformos_liquid/source_index/parameter_entry.rb +25 -0
- data/lib/platformos_check/platformos_liquid/source_index/property_entry.rb +21 -0
- data/lib/platformos_check/platformos_liquid/source_index/return_type_entry.rb +41 -0
- data/lib/platformos_check/platformos_liquid/source_index/tag_entry.rb +24 -0
- data/lib/platformos_check/platformos_liquid/source_index/tag_state.rb +11 -0
- data/lib/platformos_check/platformos_liquid/source_index.rb +79 -0
- data/lib/platformos_check/platformos_liquid/source_manager.rb +116 -0
- data/lib/platformos_check/platformos_liquid/tag.rb +59 -0
- data/lib/platformos_check/platformos_liquid.rb +21 -0
- data/lib/platformos_check/position.rb +180 -0
- data/lib/platformos_check/position_helper.rb +57 -0
- data/lib/platformos_check/printer.rb +87 -0
- data/lib/platformos_check/regex_helpers.rb +21 -0
- data/lib/platformos_check/releaser.rb +43 -0
- data/lib/platformos_check/schema_file.rb +6 -0
- data/lib/platformos_check/sms_file.rb +9 -0
- data/lib/platformos_check/storage.rb +29 -0
- data/lib/platformos_check/string_helpers.rb +48 -0
- data/lib/platformos_check/tags/background.rb +67 -0
- data/lib/platformos_check/tags/base.rb +14 -0
- data/lib/platformos_check/tags/base_block.rb +14 -0
- data/lib/platformos_check/tags/base_tag_methods.rb +59 -0
- data/lib/platformos_check/tags/cache.rb +13 -0
- data/lib/platformos_check/tags/export.rb +30 -0
- data/lib/platformos_check/tags/form.rb +19 -0
- data/lib/platformos_check/tags/function.rb +58 -0
- data/lib/platformos_check/tags/graphql.rb +70 -0
- data/lib/platformos_check/tags/hash_assign.rb +75 -0
- data/lib/platformos_check/tags/log.rb +15 -0
- data/lib/platformos_check/tags/parse_json.rb +24 -0
- data/lib/platformos_check/tags/print.rb +20 -0
- data/lib/platformos_check/tags/redirect_to.rb +15 -0
- data/lib/platformos_check/tags/render.rb +60 -0
- data/lib/platformos_check/tags/response_headers.rb +20 -0
- data/lib/platformos_check/tags/response_status.rb +20 -0
- data/lib/platformos_check/tags/return.rb +20 -0
- data/lib/platformos_check/tags/session.rb +27 -0
- data/lib/platformos_check/tags/sign_in.rb +27 -0
- data/lib/platformos_check/tags/spam_protection.rb +15 -0
- data/lib/platformos_check/tags/theme_render.rb +58 -0
- data/lib/platformos_check/tags/try.rb +59 -0
- data/lib/platformos_check/tags.rb +65 -0
- data/lib/platformos_check/translation_file.rb +6 -0
- data/lib/platformos_check/user_schema_file.rb +6 -0
- data/lib/platformos_check/version.rb +5 -0
- data/lib/platformos_check/yaml_check.rb +11 -0
- data/lib/platformos_check/yaml_file.rb +57 -0
- data/lib/platformos_check.rb +106 -0
- data/platformos-check.gemspec +34 -0
- metadata +329 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PlatformosCheck
|
|
4
|
+
module PlatformosLiquid
|
|
5
|
+
class SourceIndex
|
|
6
|
+
class ParameterEntry < BaseEntry
|
|
7
|
+
def summary
|
|
8
|
+
nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def platformos_documentation_url
|
|
12
|
+
"#{PLATFORMOS_DOCUMENTATION_URL}/api-reference/liquid/filters/#{hash['name']}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def return_type_hash
|
|
18
|
+
{
|
|
19
|
+
'type' => (hash['types'] || ['untyped']).first
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PlatformosCheck
|
|
4
|
+
module PlatformosLiquid
|
|
5
|
+
class SourceIndex
|
|
6
|
+
class PropertyEntry < BaseEntry
|
|
7
|
+
attr_reader :parent_name
|
|
8
|
+
|
|
9
|
+
def initialize(hash, parent_name)
|
|
10
|
+
@hash = hash || {}
|
|
11
|
+
@return_type = nil
|
|
12
|
+
@parent_name = parent_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def platformos_documentation_url
|
|
16
|
+
"#{PLATFORMOS_DOCUMENTATION_URL}/developer-guide/variables/context-variable##{@parent_name}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PlatformosCheck
|
|
4
|
+
module PlatformosLiquid
|
|
5
|
+
class SourceIndex
|
|
6
|
+
class ReturnTypeEntry < BaseEntry
|
|
7
|
+
def summary
|
|
8
|
+
nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
hash['type']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def generic_type?
|
|
16
|
+
hash['type'] == 'generic'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def array_type?
|
|
20
|
+
!array_type.nil? && !array_type.empty?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def array_type
|
|
24
|
+
hash['array_value']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def denied_filters
|
|
28
|
+
hash['denied_filters'] || []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def return_type_hash
|
|
34
|
+
{
|
|
35
|
+
'type' => "type<#{self}>"
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PlatformosCheck
|
|
4
|
+
module PlatformosLiquid
|
|
5
|
+
class SourceIndex
|
|
6
|
+
class TagEntry < BaseEntry
|
|
7
|
+
def parameters
|
|
8
|
+
(hash['parameters'] || [])
|
|
9
|
+
.map { |hash| ParameterEntry.new(hash) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def return_type_hash
|
|
13
|
+
{
|
|
14
|
+
'type' => "tag<#{name}>"
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def platformos_documentation_url
|
|
19
|
+
"#{PLATFORMOS_DOCUMENTATION_URL}/api-reference/liquid/tags/#{hash['name']}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
|
|
6
|
+
module PlatformosCheck
|
|
7
|
+
module PlatformosLiquid
|
|
8
|
+
class SourceIndex
|
|
9
|
+
class << self
|
|
10
|
+
def filters
|
|
11
|
+
@filters = nil if FilterState.outdated?
|
|
12
|
+
|
|
13
|
+
@filters ||= FilterState.mark_up_to_date &&
|
|
14
|
+
load_file(:filters)
|
|
15
|
+
.map { |hash| FilterEntry.new(hash) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def objects
|
|
19
|
+
@objects = nil if ObjectState.outdated?
|
|
20
|
+
|
|
21
|
+
@objects ||= ObjectState.mark_up_to_date &&
|
|
22
|
+
load_file(:objects)
|
|
23
|
+
.concat(built_in_objects)
|
|
24
|
+
.filter_map do |hash|
|
|
25
|
+
next if labels_only_exposed_in_certain_contexts.include?(hash['name'])
|
|
26
|
+
|
|
27
|
+
ObjectEntry.new(hash)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def tags
|
|
32
|
+
@tags = nil if TagState.outdated?
|
|
33
|
+
|
|
34
|
+
@tags ||= TagState.mark_up_to_date &&
|
|
35
|
+
load_file(:tags)
|
|
36
|
+
.map { |hash| TagEntry.new(hash) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def plus_labels
|
|
40
|
+
@plus_objects ||= load_file("../plus_labels")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def platformos_app_app_extension_labels
|
|
44
|
+
@platformos_app_app_extension_labels ||= load_file("../platformos_app_app_extension_labels")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def labels_only_exposed_in_certain_contexts
|
|
48
|
+
%w[robots app].freeze
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def deprecated_filters
|
|
52
|
+
@deprecated_filters ||= load_file("../deprecated_filters")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def load_file(file_name)
|
|
58
|
+
read_json(local_path!(file_name))
|
|
59
|
+
rescue StandardError
|
|
60
|
+
# If files get manually deleted, fallback with an empty list.
|
|
61
|
+
[]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def local_path!(file_name)
|
|
65
|
+
SourceManager.download unless SourceManager.has_required_files?
|
|
66
|
+
SourceManager.local_path(file_name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def read_json(path)
|
|
70
|
+
JSON.parse(path.read)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def built_in_objects
|
|
74
|
+
load_file('../built_in_liquid_objects')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
module PlatformosCheck
|
|
8
|
+
module PlatformosLiquid
|
|
9
|
+
class SourceManager
|
|
10
|
+
REQUIRED_FILE_NAMES = %i[filters objects tags latest].freeze
|
|
11
|
+
|
|
12
|
+
class DownloadResourceError < StandardError; end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def download_or_refresh_files(destination = default_destination)
|
|
16
|
+
if has_required_files?(destination)
|
|
17
|
+
refresh(destination)
|
|
18
|
+
else
|
|
19
|
+
download(destination)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def download(destination = default_destination)
|
|
24
|
+
Dir.mkdir(destination) unless destination.exist?
|
|
25
|
+
|
|
26
|
+
REQUIRED_FILE_NAMES.each do |file_name|
|
|
27
|
+
download_file(local_path(file_name, destination), remote_path(file_name))
|
|
28
|
+
end
|
|
29
|
+
rescue DownloadResourceError
|
|
30
|
+
# If a request error occurs, ignore it. This ensures that PlatformOS Check
|
|
31
|
+
# can rely on the sources included during the bundling phase.
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def refresh(destination = default_destination)
|
|
35
|
+
refresh_threads << Thread.new { refresh_thread(destination) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def local_path(file_name, destination = default_destination)
|
|
39
|
+
destination + "#{file_name}.json"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def has_required_files?(destination = default_destination)
|
|
43
|
+
REQUIRED_FILE_NAMES.all? { |file_name| local_path(file_name, destination).exist? }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def wait_downloads
|
|
47
|
+
refresh_threads.each(&:join)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def refresh_thread(destination)
|
|
53
|
+
return unless refresh_needed?(destination)
|
|
54
|
+
|
|
55
|
+
Dir.mktmpdir do |tmp_dir|
|
|
56
|
+
download(Pathname.new(tmp_dir))
|
|
57
|
+
|
|
58
|
+
FileUtils.cp_r("#{tmp_dir}/.", destination)
|
|
59
|
+
|
|
60
|
+
mark_all_indexes_outdated
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def refresh_needed?(destination)
|
|
65
|
+
local_latest_content = local_path(:latest, destination).read
|
|
66
|
+
remote_latest_content = open_uri(remote_path(:latest))
|
|
67
|
+
|
|
68
|
+
revision(local_latest_content) != revision(remote_latest_content)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def revision(json_content)
|
|
72
|
+
# Raise an error if revision isn't found to avoid returning nil
|
|
73
|
+
JSON.parse(json_content).fetch('revision')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def remote_path(file_name)
|
|
77
|
+
"https://documentation.platformos.com/api/liquid/#{file_name}.json"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def download_file(local_path, remote_uri)
|
|
81
|
+
content = open_uri(remote_uri)
|
|
82
|
+
File.binwrite(local_path, content)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def mark_all_indexes_outdated
|
|
86
|
+
SourceIndex::FilterState.mark_outdated
|
|
87
|
+
SourceIndex::ObjectState.mark_outdated
|
|
88
|
+
SourceIndex::TagState.mark_outdated
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# State
|
|
92
|
+
|
|
93
|
+
def default_destination
|
|
94
|
+
@default_destination ||= Pathname.new("#{__dir__}/../../../data/platformos_liquid/documentation")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def refresh_threads
|
|
98
|
+
@refresh_threads ||= []
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def open_uri(uri_str)
|
|
102
|
+
uri = URI.parse(uri_str)
|
|
103
|
+
|
|
104
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
105
|
+
req = Net::HTTP::Get.new(uri)
|
|
106
|
+
http.request(req)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
res.body
|
|
110
|
+
rescue StandardError
|
|
111
|
+
raise DownloadResourceError
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module PlatformosCheck
|
|
6
|
+
module PlatformosLiquid
|
|
7
|
+
module Tag
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
LABELS_NOT_IN_SOURCE_INDEX = %w[elsif ifchanged catch ensure when]
|
|
11
|
+
|
|
12
|
+
def labels
|
|
13
|
+
@labels ||= tags_file_contents
|
|
14
|
+
.map { |x| to_label(x) }
|
|
15
|
+
.to_set
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def end_labels
|
|
19
|
+
@end_labels ||= tags_file_contents
|
|
20
|
+
.select { |x| x.is_a?(Hash) }
|
|
21
|
+
.map { |x| x.values[0] }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def tag_regex(tag)
|
|
25
|
+
return unless labels.include?(tag)
|
|
26
|
+
|
|
27
|
+
@tag_regexes ||= {}
|
|
28
|
+
@tag_regexes[tag] ||= /\A#{Liquid::TagStart}-?\s*#{tag}/m
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def liquid_tag_regex(tag)
|
|
32
|
+
return unless labels.include?(tag)
|
|
33
|
+
|
|
34
|
+
@tag_liquid_regexes ||= {}
|
|
35
|
+
@tag_liquid_regexes[tag] ||= /^\s*#{tag}/m
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def to_label(label)
|
|
41
|
+
return label if label.is_a?(String)
|
|
42
|
+
|
|
43
|
+
label.keys[0]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def tags_file_contents
|
|
47
|
+
@tags_file_contents ||= SourceIndex.tags.map do |tag|
|
|
48
|
+
opening_tag = tag.name
|
|
49
|
+
closing_tag = "end#{opening_tag}"
|
|
50
|
+
if /#{opening_tag}.+#{closing_tag}/m.match?(tag.hash['syntax'])
|
|
51
|
+
{ opening_tag => closing_tag }
|
|
52
|
+
else
|
|
53
|
+
opening_tag
|
|
54
|
+
end
|
|
55
|
+
end + LABELS_NOT_IN_SOURCE_INDEX
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'platformos_liquid/deprecated_filter'
|
|
4
|
+
require_relative 'platformos_liquid/documentation'
|
|
5
|
+
require_relative 'platformos_liquid/filter'
|
|
6
|
+
require_relative 'platformos_liquid/object'
|
|
7
|
+
require_relative 'platformos_liquid/source_manager'
|
|
8
|
+
require_relative 'platformos_liquid/source_index'
|
|
9
|
+
require_relative 'platformos_liquid/tag'
|
|
10
|
+
|
|
11
|
+
require_relative 'platformos_liquid/source_index/base_entry'
|
|
12
|
+
require_relative 'platformos_liquid/source_index/filter_entry'
|
|
13
|
+
require_relative 'platformos_liquid/source_index/object_entry'
|
|
14
|
+
require_relative 'platformos_liquid/source_index/parameter_entry'
|
|
15
|
+
require_relative 'platformos_liquid/source_index/property_entry'
|
|
16
|
+
require_relative 'platformos_liquid/source_index/return_type_entry'
|
|
17
|
+
require_relative 'platformos_liquid/source_index/tag_entry'
|
|
18
|
+
require_relative 'platformos_liquid/source_index/base_state'
|
|
19
|
+
require_relative 'platformos_liquid/source_index/filter_state'
|
|
20
|
+
require_relative 'platformos_liquid/source_index/object_state'
|
|
21
|
+
require_relative 'platformos_liquid/source_index/tag_state'
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PlatformosCheck
|
|
4
|
+
class Position
|
|
5
|
+
include PositionHelper
|
|
6
|
+
|
|
7
|
+
attr_reader :contents
|
|
8
|
+
|
|
9
|
+
def initialize(
|
|
10
|
+
needle_arg,
|
|
11
|
+
contents_arg,
|
|
12
|
+
line_number_1_indexed: nil,
|
|
13
|
+
node_markup: nil,
|
|
14
|
+
node_markup_offset: 0 # the index of markup inside the node_markup
|
|
15
|
+
)
|
|
16
|
+
@needle = needle_arg
|
|
17
|
+
|
|
18
|
+
@contents = if contents_arg.is_a?(String) && !contents_arg.empty?
|
|
19
|
+
contents_arg
|
|
20
|
+
else
|
|
21
|
+
''
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@line_number_1_indexed = line_number_1_indexed
|
|
25
|
+
@node_markup_offset = node_markup_offset
|
|
26
|
+
@node_markup = node_markup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def start_line_offset
|
|
30
|
+
@start_line_offset ||= from_row_column_to_index(contents, line_number, 0)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def start_offset
|
|
34
|
+
@start_offset ||= compute_start_offset
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def strict_position
|
|
38
|
+
@strict_position ||= StrictPosition.new(
|
|
39
|
+
needle,
|
|
40
|
+
contents,
|
|
41
|
+
start_index
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# 0-indexed, inclusive
|
|
46
|
+
def start_index
|
|
47
|
+
contents.index(needle, start_offset)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# 0-indexed, exclusive
|
|
51
|
+
def end_index
|
|
52
|
+
strict_position.end_index
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# 0-indexed, inclusive
|
|
56
|
+
def start_row
|
|
57
|
+
strict_position.start_row
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# 0-indexed, inclusive
|
|
61
|
+
def start_column
|
|
62
|
+
strict_position.start_column
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# 0-indexed, exclusive (both taken together are) therefore you
|
|
66
|
+
# might end up on a newline character or the next line
|
|
67
|
+
def end_row
|
|
68
|
+
strict_position.end_row
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def end_column
|
|
72
|
+
strict_position.end_column
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def content_line_count
|
|
76
|
+
@content_line_count ||= contents.count("\n")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def compute_start_offset
|
|
82
|
+
return start_line_offset if @node_markup.nil?
|
|
83
|
+
|
|
84
|
+
node_markup_start = contents.index(@node_markup, start_line_offset)
|
|
85
|
+
return start_line_offset if node_markup_start.nil?
|
|
86
|
+
|
|
87
|
+
node_markup_start + @node_markup_offset
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def line_number
|
|
91
|
+
return 0 if @line_number_1_indexed.nil?
|
|
92
|
+
|
|
93
|
+
bounded(0, @line_number_1_indexed - 1, content_line_count)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def needle
|
|
97
|
+
@cached_needle ||= if has_content_and_line_number_but_no_needle?
|
|
98
|
+
entire_line_needle
|
|
99
|
+
elsif contents.empty? || @needle.nil?
|
|
100
|
+
''
|
|
101
|
+
elsif !can_find_needle?
|
|
102
|
+
entire_line_needle
|
|
103
|
+
else
|
|
104
|
+
@needle
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def has_content_and_line_number_but_no_needle?
|
|
109
|
+
@needle.nil? && !contents.empty? && @line_number_1_indexed.is_a?(Integer)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def can_find_needle?
|
|
113
|
+
!!contents.index(@needle, start_offset)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def entire_line_needle
|
|
117
|
+
contents.lines(chomp: true)[line_number] || ''
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# This method is stricter than Position in the sense that it doesn't
|
|
122
|
+
# accept invalid inputs. Makes for code that is easier to understand.
|
|
123
|
+
class StrictPosition
|
|
124
|
+
include PositionHelper
|
|
125
|
+
|
|
126
|
+
attr_reader :needle, :contents
|
|
127
|
+
|
|
128
|
+
def initialize(needle, contents, start_index)
|
|
129
|
+
raise ArgumentError, 'Bad start_index' unless start_index.is_a?(Integer)
|
|
130
|
+
raise ArgumentError, 'Bad contents' unless contents.is_a?(String)
|
|
131
|
+
raise ArgumentError, 'Bad needle' unless needle.is_a?(String) || !contents.index(needle, start_index)
|
|
132
|
+
|
|
133
|
+
@needle = needle
|
|
134
|
+
@contents = contents
|
|
135
|
+
@start_index = start_index
|
|
136
|
+
@start_row_column = nil
|
|
137
|
+
@end_row_column = nil
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# 0-indexed, inclusive
|
|
141
|
+
def start_index
|
|
142
|
+
@contents.index(needle, @start_index)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# 0-indexed, exclusive
|
|
146
|
+
def end_index
|
|
147
|
+
start_index + needle.size
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def start_row
|
|
151
|
+
start_row_column[0]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def start_column
|
|
155
|
+
start_row_column[1]
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def end_row
|
|
159
|
+
end_row_column[0]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def end_column
|
|
163
|
+
end_row_column[1]
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
def start_row_column
|
|
169
|
+
return @start_row_column unless @start_row_column.nil?
|
|
170
|
+
|
|
171
|
+
@start_row_column = from_index_to_row_column(contents, start_index)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def end_row_column
|
|
175
|
+
return @end_row_column unless @end_row_column.nil?
|
|
176
|
+
|
|
177
|
+
@end_row_column = from_index_to_row_column(contents, end_index)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# NOTE: Everything is 0-indexed here.
|
|
4
|
+
|
|
5
|
+
module PlatformosCheck
|
|
6
|
+
module PositionHelper
|
|
7
|
+
# Apparently this old implementation is 2x slower (with benchmark/ips),
|
|
8
|
+
# so dropping with the following one... It's ugly af but
|
|
9
|
+
# this shit runs 100K+ times in one platformos-check so it gotta go
|
|
10
|
+
# fast!
|
|
11
|
+
#
|
|
12
|
+
def from_row_column_to_index(content, row, col)
|
|
13
|
+
return 0 unless content.is_a?(String) && !content.empty?
|
|
14
|
+
return 0 unless row.is_a?(Integer) && col.is_a?(Integer)
|
|
15
|
+
|
|
16
|
+
i = 0
|
|
17
|
+
safe_row = bounded(0, row, content.count("\n"))
|
|
18
|
+
scanner = StringScanner.new(content)
|
|
19
|
+
scanner.scan_until(/\n/) while i < safe_row && (i += 1)
|
|
20
|
+
result = scanner.charpos || 0
|
|
21
|
+
scanner.scan_until(/\n|\z/)
|
|
22
|
+
bounded(result, result + col, scanner.pre_match.size)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# def from_row_column_to_index(content, row, col)
|
|
26
|
+
# return 0 unless content.is_a?(String) && !content.empty?
|
|
27
|
+
# return 0 unless row.is_a?(Integer) && col.is_a?(Integer)
|
|
28
|
+
# i = 0
|
|
29
|
+
# safe_row = bounded(0, row, content.count("\n"))
|
|
30
|
+
# charpos = -1
|
|
31
|
+
# charpos = content.index("\n", charpos + 1) while i < safe_row && (i += 1) && charpos
|
|
32
|
+
# result = charpos ? charpos + 1 : 0
|
|
33
|
+
# next_line = content.index("\n", result)
|
|
34
|
+
# upper_bound = next_line ? next_line : content.size - 1
|
|
35
|
+
# bounded(result, result + col, upper_bound)
|
|
36
|
+
# end
|
|
37
|
+
|
|
38
|
+
def from_index_to_row_column(content, index)
|
|
39
|
+
return [0, 0] unless content.is_a?(String) && !content.empty?
|
|
40
|
+
return [0, 0] unless index.is_a?(Integer)
|
|
41
|
+
|
|
42
|
+
safe_index = bounded(0, index, content.size - 1)
|
|
43
|
+
content_up_to_index = content[0...safe_index]
|
|
44
|
+
row = content_up_to_index.count("\n")
|
|
45
|
+
col = 0
|
|
46
|
+
col += 1 while (safe_index -= 1) && safe_index >= 0 && content[safe_index] != "\n"
|
|
47
|
+
[row, col]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def bounded(a, x, b)
|
|
51
|
+
return a if x < a
|
|
52
|
+
return b if x > b
|
|
53
|
+
|
|
54
|
+
x
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|