platformos-check 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,219 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
class Config
|
5
|
+
DOTFILE = '.platformos-check.yml'
|
6
|
+
BUNDLED_CONFIGS_DIR = Pathname.new("#{__dir__}/../../config").realpath
|
7
|
+
BOOLEAN = [true, false]
|
8
|
+
|
9
|
+
attr_reader :root
|
10
|
+
attr_accessor :auto_correct
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :last_loaded_config
|
14
|
+
|
15
|
+
def from_path(path)
|
16
|
+
if (filename = find(path))
|
17
|
+
new(root: filename.dirname, configuration: load_config(filename))
|
18
|
+
else
|
19
|
+
# No configuration file
|
20
|
+
new(root: path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_string(config)
|
25
|
+
new(configuration: YAML.load(config), should_resolve_requires: false)
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_hash(config)
|
29
|
+
new(configuration: config, should_resolve_requires: false)
|
30
|
+
end
|
31
|
+
|
32
|
+
def find(root, needle = DOTFILE)
|
33
|
+
Pathname.new(root).descend.reverse_each do |path|
|
34
|
+
pathname = path.join(needle)
|
35
|
+
return pathname if pathname.exist?
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_file(absolute_path)
|
41
|
+
@last_loaded_config = absolute_path
|
42
|
+
# An empty file returns false, so we || {}.
|
43
|
+
YAML.load_file(absolute_path) || {}
|
44
|
+
end
|
45
|
+
|
46
|
+
def bundled_config_path(name)
|
47
|
+
"#{BUNDLED_CONFIGS_DIR}/#{name.to_s.sub(/^:/, '')}.yml"
|
48
|
+
end
|
49
|
+
|
50
|
+
def bundled_config?(name)
|
51
|
+
name.is_a?(Symbol) || (name.is_a?(String) && name[0] == ":")
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_bundled_config(name)
|
55
|
+
load_file(bundled_config_path(name))
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_config(name, pwd = Pathname.pwd)
|
59
|
+
return load_bundled_config(name) if bundled_config?(name)
|
60
|
+
|
61
|
+
path = name.is_a?(Pathname) ? name : Pathname.new(name)
|
62
|
+
path = pwd.join(path) if path.relative?
|
63
|
+
return {} unless path.exist?
|
64
|
+
|
65
|
+
config = load_file(path)
|
66
|
+
extends = config["extends"] || :default
|
67
|
+
merge_configurations!(load_config(extends, path.realpath.dirname), config)
|
68
|
+
end
|
69
|
+
|
70
|
+
def merge_configurations!(config, other)
|
71
|
+
config.merge(other) do |_key, old_value, new_value|
|
72
|
+
case old_value
|
73
|
+
when Hash
|
74
|
+
merge_configurations!(old_value, new_value)
|
75
|
+
else
|
76
|
+
new_value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def default
|
82
|
+
load_config(":default")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize(root: nil, configuration: nil, should_resolve_requires: true)
|
87
|
+
@configuration = if configuration
|
88
|
+
validate_configuration(configuration)
|
89
|
+
else
|
90
|
+
self.class.default
|
91
|
+
end
|
92
|
+
|
93
|
+
extends = @configuration["extends"] || :default
|
94
|
+
@configuration = self.class.merge_configurations!(self.class.load_config(extends), @configuration)
|
95
|
+
|
96
|
+
@root = if root && @configuration.key?("root")
|
97
|
+
Pathname.new(root).join(@configuration["root"])
|
98
|
+
elsif root
|
99
|
+
Pathname.new(root)
|
100
|
+
end
|
101
|
+
|
102
|
+
@auto_correct = false
|
103
|
+
|
104
|
+
resolve_requires if @root && should_resolve_requires
|
105
|
+
end
|
106
|
+
|
107
|
+
def [](name)
|
108
|
+
@configuration[name]
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_h
|
112
|
+
@configuration
|
113
|
+
end
|
114
|
+
|
115
|
+
def check_configurations
|
116
|
+
@check_configurations ||= @configuration.select { |name, _| check_name?(name) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def enabled_checks
|
120
|
+
@enabled_checks ||= check_configurations.map do |check_name, options|
|
121
|
+
next unless options["enabled"]
|
122
|
+
|
123
|
+
check_class = PlatformosCheck.const_get(check_name)
|
124
|
+
|
125
|
+
next if check_class.categories.any? { |category| exclude_categories.include?(category) }
|
126
|
+
next if include_categories.any? && !include_categories.all? { |category| check_class.categories.include?(category) }
|
127
|
+
|
128
|
+
options_for_check = options.transform_keys(&:to_sym)
|
129
|
+
options_for_check.delete(:enabled)
|
130
|
+
severity = options_for_check.delete(:severity)
|
131
|
+
check_ignored_patterns = options_for_check.delete(:ignore) || []
|
132
|
+
check = if options_for_check.empty?
|
133
|
+
check_class.new
|
134
|
+
else
|
135
|
+
check_class.new(**options_for_check)
|
136
|
+
end
|
137
|
+
check.severity = severity.to_sym if severity
|
138
|
+
check.ignored_patterns = check_ignored_patterns + ignored_patterns
|
139
|
+
check.options = options_for_check
|
140
|
+
check
|
141
|
+
end.compact
|
142
|
+
end
|
143
|
+
|
144
|
+
def ignored_patterns
|
145
|
+
self["ignore"] || []
|
146
|
+
end
|
147
|
+
|
148
|
+
def include_categories
|
149
|
+
self["include_categories"] || []
|
150
|
+
end
|
151
|
+
|
152
|
+
def include_categories=(categories)
|
153
|
+
@configuration["include_categories"] = categories
|
154
|
+
end
|
155
|
+
|
156
|
+
def exclude_categories
|
157
|
+
self["exclude_categories"] || []
|
158
|
+
end
|
159
|
+
|
160
|
+
def exclude_categories=(categories)
|
161
|
+
@configuration["exclude_categories"] = categories
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def check_name?(name)
|
167
|
+
name.to_s.start_with?(/[A-Z]/)
|
168
|
+
end
|
169
|
+
|
170
|
+
def validate_configuration(configuration, default_configuration = self.class.default, parent_keys = [])
|
171
|
+
valid_configuration = {}
|
172
|
+
|
173
|
+
configuration.each do |key, value|
|
174
|
+
# No validation possible unless we have a default to compare to
|
175
|
+
unless default_configuration
|
176
|
+
valid_configuration[key] = value
|
177
|
+
next
|
178
|
+
end
|
179
|
+
|
180
|
+
default = default_configuration[key]
|
181
|
+
keys = parent_keys + [key]
|
182
|
+
name = keys.join(".")
|
183
|
+
|
184
|
+
if check_name?(key)
|
185
|
+
if value.is_a?(Hash)
|
186
|
+
valid_configuration[key] = validate_configuration(value, default, keys)
|
187
|
+
else
|
188
|
+
warn("bad configuration type for #{name}: expected a Hash, got #{value.inspect}")
|
189
|
+
end
|
190
|
+
elsif key == "extends"
|
191
|
+
if value.is_a?(Symbol) || value.is_a?(String)
|
192
|
+
valid_configuration[key] = value
|
193
|
+
else
|
194
|
+
warn("bad configuration type for extends: expected a Symbol or a String, got #{value.inspect}")
|
195
|
+
end
|
196
|
+
elsif key == "severity"
|
197
|
+
valid_configuration[key] = value
|
198
|
+
elsif default.nil?
|
199
|
+
warn("unknown configuration: #{name}")
|
200
|
+
elsif BOOLEAN.include?(default) && !BOOLEAN.include?(value)
|
201
|
+
warn("bad configuration type for #{name}: expected true or false, got #{value.inspect}")
|
202
|
+
elsif !BOOLEAN.include?(default) && default.class != value.class
|
203
|
+
warn("bad configuration type for #{name}: expected a #{default.class}, got #{value.inspect}")
|
204
|
+
else
|
205
|
+
valid_configuration[key] = value
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
valid_configuration
|
210
|
+
end
|
211
|
+
|
212
|
+
def resolve_requires
|
213
|
+
self["require"]&.each do |path|
|
214
|
+
file_to_require = @root.join(path).realpath
|
215
|
+
require(file_to_require.to_s)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
class Corrector
|
5
|
+
include JsonHelpers
|
6
|
+
|
7
|
+
def initialize(app_file:)
|
8
|
+
@app_file = app_file
|
9
|
+
end
|
10
|
+
|
11
|
+
def insert_after(node, content, character_range = nil)
|
12
|
+
@app_file.rewriter.insert_after(node, content, character_range)
|
13
|
+
end
|
14
|
+
|
15
|
+
def insert_before(node, content, character_range = nil)
|
16
|
+
@app_file.rewriter.insert_before(node, content, character_range)
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove(node)
|
20
|
+
@app_file.rewriter.remove(node)
|
21
|
+
end
|
22
|
+
|
23
|
+
def replace(node, content, character_range = nil)
|
24
|
+
@app_file.rewriter.replace(node, content, character_range)
|
25
|
+
node.markup = content
|
26
|
+
end
|
27
|
+
|
28
|
+
def replace_inner_markup(node, content)
|
29
|
+
@app_file.rewriter.replace_inner_markup(node, content)
|
30
|
+
end
|
31
|
+
|
32
|
+
def replace_inner_json(node, json, **)
|
33
|
+
replace_inner_markup(node, pretty_json(json, **))
|
34
|
+
end
|
35
|
+
|
36
|
+
def wrap(node, insert_before, insert_after)
|
37
|
+
@app_file.rewriter.wrap(node, insert_before, insert_after)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_file(storage, relative_path, content)
|
41
|
+
storage.write(relative_path, content)
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove_file(storage, relative_path)
|
45
|
+
storage.remove(relative_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
def mkdir(storage, relative_path)
|
49
|
+
storage.mkdir(relative_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
# def rename(storage, old_path, new_path)
|
53
|
+
# storage.rename(old_path, new_path)
|
54
|
+
# end
|
55
|
+
|
56
|
+
def add_translation(json_file, path, value)
|
57
|
+
hash = json_file.content
|
58
|
+
JsonHelper.set(hash, path, value)
|
59
|
+
json_file.update_contents(hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
def remove_translation(json_file, path)
|
63
|
+
hash = json_file.content
|
64
|
+
JsonHelper.delete(hash, path)
|
65
|
+
json_file.update_contents(hash)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class keeps track of checks being turned on and off in ranges.
|
4
|
+
# We'll use the node position to figure out if the test is disabled or not.
|
5
|
+
module PlatformosCheck
|
6
|
+
class DisabledCheck
|
7
|
+
attr_reader :name, :app_file, :ranges
|
8
|
+
attr_accessor :first_line
|
9
|
+
|
10
|
+
def initialize(app_file, name)
|
11
|
+
@app_file = app_file
|
12
|
+
@name = name
|
13
|
+
@ranges = []
|
14
|
+
@first_line = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_index=(index)
|
18
|
+
return unless ranges.empty? || !last.end.nil?
|
19
|
+
|
20
|
+
@ranges << (index..)
|
21
|
+
end
|
22
|
+
|
23
|
+
def end_index=(index)
|
24
|
+
return if ranges.empty? || !last.end.nil?
|
25
|
+
|
26
|
+
@ranges << (@ranges.pop.begin..index)
|
27
|
+
end
|
28
|
+
|
29
|
+
def disabled?(index)
|
30
|
+
(index == 0 && first_line) ||
|
31
|
+
ranges.any? { |range| range.cover?(index) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def last
|
35
|
+
ranges.last
|
36
|
+
end
|
37
|
+
|
38
|
+
def missing_end_index?
|
39
|
+
return false if first_line && ranges.size == 1
|
40
|
+
|
41
|
+
last&.end.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
class DisabledChecks
|
5
|
+
DISABLE_START = 'platformos-check-disable'
|
6
|
+
DISABLE_END = 'platformos-check-enable'
|
7
|
+
DISABLE_PREFIX_PATTERN = /#{DISABLE_START}|#{DISABLE_END}/
|
8
|
+
|
9
|
+
ACTION_DISABLE_CHECKS = :disable
|
10
|
+
ACTION_ENABLE_CHECKS = :enable
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@disabled_checks = Hash.new do |hash, key|
|
14
|
+
app_file, check_name = key
|
15
|
+
hash[key] = DisabledCheck.new(app_file, check_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def update(node)
|
20
|
+
text = comment_text(node)
|
21
|
+
if start_disabling?(text)
|
22
|
+
checks_from_text(text).each do |check_name|
|
23
|
+
disabled = @disabled_checks[[node.app_file, check_name]]
|
24
|
+
disabled.start_index = node.start_index
|
25
|
+
disabled.first_line = true if node.line_number == 1
|
26
|
+
end
|
27
|
+
elsif stop_disabling?(text)
|
28
|
+
checks_from_text(text).each do |check_name|
|
29
|
+
disabled = @disabled_checks[[node.app_file, check_name]]
|
30
|
+
next unless disabled
|
31
|
+
|
32
|
+
disabled.end_index = node.end_index
|
33
|
+
end
|
34
|
+
else
|
35
|
+
# We want to disable checks inside comments
|
36
|
+
# (e.g. html checks inside {% comment %})
|
37
|
+
disabled = @disabled_checks[[node.app_file, :all]]
|
38
|
+
unless disabled.first_line
|
39
|
+
disabled.start_index = node.inner_markup_start_index
|
40
|
+
disabled.end_index = node.inner_markup_end_index
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def disabled?(check, app_file, check_name, index)
|
46
|
+
return true if check.ignored_patterns&.any? do |pattern|
|
47
|
+
app_file&.relative_path&.fnmatch?(pattern)
|
48
|
+
end
|
49
|
+
|
50
|
+
@disabled_checks[[app_file, :all]]&.disabled?(index) ||
|
51
|
+
@disabled_checks[[app_file, check_name]]&.disabled?(index)
|
52
|
+
end
|
53
|
+
|
54
|
+
def checks_missing_end_index
|
55
|
+
@disabled_checks.values
|
56
|
+
.select(&:missing_end_index?)
|
57
|
+
.map(&:name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove_disabled_offenses(checks)
|
61
|
+
checks.disableable.each do |check|
|
62
|
+
check.offenses.reject! do |offense|
|
63
|
+
disabled?(check, offense.app_file, offense.code_name, offense.start_index)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def comment_text(node)
|
71
|
+
case node.type_name
|
72
|
+
when :comment
|
73
|
+
node.value.nodelist.join
|
74
|
+
when :inline_comment
|
75
|
+
node.markup.sub(/\s*#+\s*/, '')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def start_disabling?(text)
|
80
|
+
text.strip.start_with?(DISABLE_START)
|
81
|
+
end
|
82
|
+
|
83
|
+
def stop_disabling?(text)
|
84
|
+
text.strip.start_with?(DISABLE_END)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return a list of checks from a platformos-check-disable comment
|
88
|
+
# Returns [:all] if all checks are meant to be disabled
|
89
|
+
def checks_from_text(text)
|
90
|
+
checks = text.gsub(DISABLE_PREFIX_PATTERN, '').strip.split(',').map(&:strip)
|
91
|
+
return [:all] if checks.empty?
|
92
|
+
|
93
|
+
checks
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
|
5
|
+
module PlatformosCheck
|
6
|
+
TIMEOUT_EXCEPTIONS = [
|
7
|
+
Net::ReadTimeout,
|
8
|
+
Net::OpenTimeout,
|
9
|
+
Net::WriteTimeout,
|
10
|
+
Errno::ETIMEDOUT,
|
11
|
+
Timeout::Error
|
12
|
+
]
|
13
|
+
|
14
|
+
CONNECTION_EXCEPTIONS = [
|
15
|
+
IOError,
|
16
|
+
EOFError,
|
17
|
+
SocketError,
|
18
|
+
Errno::EINVAL,
|
19
|
+
Errno::ECONNRESET,
|
20
|
+
Errno::ECONNABORTED,
|
21
|
+
Errno::EPIPE,
|
22
|
+
Errno::ECONNREFUSED,
|
23
|
+
Errno::EAGAIN,
|
24
|
+
Errno::EHOSTUNREACH,
|
25
|
+
Errno::ENETUNREACH,
|
26
|
+
Errno::EADDRNOTAVAIL
|
27
|
+
]
|
28
|
+
|
29
|
+
NET_HTTP_EXCEPTIONS = [
|
30
|
+
Net::HTTPBadResponse,
|
31
|
+
Net::HTTPHeaderSyntaxError,
|
32
|
+
Net::ProtocolError,
|
33
|
+
*TIMEOUT_EXCEPTIONS,
|
34
|
+
*CONNECTION_EXCEPTIONS
|
35
|
+
]
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
module PlatformosCheck
|
6
|
+
class FileSystemStorage < Storage
|
7
|
+
attr_reader :root
|
8
|
+
|
9
|
+
def initialize(root, ignored_patterns: [])
|
10
|
+
@root = Pathname.new(root)
|
11
|
+
@ignored_patterns = ignored_patterns
|
12
|
+
@files = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def relative_path(absolute_path)
|
16
|
+
Pathname.new(absolute_path).relative_path_from(@root).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def path(relative_path)
|
20
|
+
@root.join(relative_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def read(relative_path)
|
24
|
+
file(relative_path).read(mode: 'rb', encoding: 'UTF-8')
|
25
|
+
rescue Errno::ENOENT
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def write(relative_path, content)
|
30
|
+
reset_memoizers unless file_exists?(relative_path)
|
31
|
+
|
32
|
+
file(relative_path).dirname.mkpath unless file(relative_path).dirname.directory?
|
33
|
+
file(relative_path).write(content, mode: 'w+b', encoding: 'UTF-8')
|
34
|
+
end
|
35
|
+
|
36
|
+
def remove(relative_path)
|
37
|
+
file(relative_path).delete
|
38
|
+
reset_memoizers
|
39
|
+
end
|
40
|
+
|
41
|
+
def mkdir(relative_path)
|
42
|
+
return if file_exists?(relative_path)
|
43
|
+
|
44
|
+
reset_memoizers
|
45
|
+
file(relative_path).mkpath
|
46
|
+
end
|
47
|
+
|
48
|
+
# TODO: Fix corrector
|
49
|
+
# def rename(old_path, new_path)
|
50
|
+
# return unless file_exists?(old_path)
|
51
|
+
#
|
52
|
+
# reset_memoizers
|
53
|
+
#
|
54
|
+
# file(old_path).mv(new_path)
|
55
|
+
# end
|
56
|
+
|
57
|
+
def files
|
58
|
+
@file_array ||= glob("**/*")
|
59
|
+
.reject { |path| File.directory?(path) }
|
60
|
+
.map { |path| path.relative_path_from(@root).to_s }
|
61
|
+
end
|
62
|
+
|
63
|
+
def directories
|
64
|
+
@directories ||= glob('**/')
|
65
|
+
.select { |f| File.directory?(f) }
|
66
|
+
.map { |f| f.relative_path_from(@root).to_s }
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def file_exists?(relative_path)
|
72
|
+
!!@files[relative_path]
|
73
|
+
end
|
74
|
+
|
75
|
+
def reset_memoizers
|
76
|
+
@file_array = nil
|
77
|
+
@directories = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def glob(pattern)
|
81
|
+
@root.glob(pattern).reject do |path|
|
82
|
+
relative_path = path.relative_path_from(@root)
|
83
|
+
@ignored_patterns.any? { |ignored| relative_path.fnmatch?(ignored) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def file(name)
|
88
|
+
return @files[name] if @files[name]
|
89
|
+
|
90
|
+
@files[name] = root.join(name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql'
|
4
|
+
|
5
|
+
module PlatformosCheck
|
6
|
+
class GraphqlFile < AppFile
|
7
|
+
DIR_PREFIX = %r{\A/?((marketplace_builder|app)/(graph_queries|graphql)s?/|modules/((\w|-)*)/(private|public)/(graph_queries|graphql)s?/)}
|
8
|
+
|
9
|
+
def write
|
10
|
+
content = rewriter.to_s
|
11
|
+
return unless source != content
|
12
|
+
|
13
|
+
@storage.write(@relative_path, content.gsub("\n", @eol))
|
14
|
+
@source = content
|
15
|
+
@rewriter = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def rewriter
|
19
|
+
@rewriter ||= AppFileRewriter.new(@relative_path, source)
|
20
|
+
end
|
21
|
+
|
22
|
+
def dir_prefix
|
23
|
+
DIR_PREFIX
|
24
|
+
end
|
25
|
+
|
26
|
+
def source_excerpt(line)
|
27
|
+
original_lines = source.split("\n")
|
28
|
+
original_lines[bounded(0, line - 1, original_lines.size - 1)].strip
|
29
|
+
rescue StandardError => e
|
30
|
+
PlatformosCheck.bug(<<~EOS)
|
31
|
+
Exception while running `source_excerpt(#{line})`:
|
32
|
+
```
|
33
|
+
#{e.class}: #{e.message}
|
34
|
+
#{e.backtrace.join("\n ")}
|
35
|
+
```
|
36
|
+
|
37
|
+
path: #{path}
|
38
|
+
|
39
|
+
source:
|
40
|
+
```
|
41
|
+
#{source}
|
42
|
+
```
|
43
|
+
EOS
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse
|
47
|
+
@parse ||= GraphQL.parse(source)
|
48
|
+
end
|
49
|
+
|
50
|
+
def warnings
|
51
|
+
@ast.warnings
|
52
|
+
end
|
53
|
+
|
54
|
+
def root
|
55
|
+
parse.root
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.parse(_source)
|
59
|
+
Struct.new(:warnings, :root)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def bounded(lower, x, upper)
|
65
|
+
[lower, [x, upper].min].max
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|