query_packwerk 0.1.25 → 0.1.26
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 +4 -4
- data/lib/query_packwerk/file_cache.rb +35 -5
- data/lib/query_packwerk/version.rb +1 -1
- data/lib/query_packwerk/violation.rb +5 -5
- data/lib/query_packwerk/violations.rb +3 -1
- data/lib/query_packwerk.rb +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 98b9a4d914a8be019fa0b1795cd527ac2bfd4ce7931b1e5a204704b5bb503847
|
|
4
|
+
data.tar.gz: 209fa3baaa03c0687daca480890ff32ec6c2111c1c902c3088771614d4127c53
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 406b5e9039a31dda4264391d1287fa89684dc21a982521c212734c05055e727ecaea62b9ed234e296a151587fd9cbaee5dd99915573f5ccb90429509f12de046
|
|
7
|
+
data.tar.gz: e11dfd82ec7324d499e37c0214d7b12ad735d03732f996bcd8e8397f36f684fd99ff6e3b58fa73a1adbc63f7e87d4be455e62814bb690e51cca0d27d7d8d22dc
|
|
@@ -9,7 +9,9 @@ module QueryPackwerk
|
|
|
9
9
|
class FileCache
|
|
10
10
|
extend T::Sig
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# The files packwerk parses as Ruby, from Packwerk::Parsers::Factory
|
|
13
|
+
RUBY_FILE = T.let(/(\.(rb|rake|builder|gemspec|ru)|Gemfile|Rakefile)\z/, Regexp)
|
|
14
|
+
ERB_FILE = T.let(/\.erb\z/, Regexp)
|
|
13
15
|
|
|
14
16
|
sig { void }
|
|
15
17
|
def initialize
|
|
@@ -62,12 +64,18 @@ module QueryPackwerk
|
|
|
62
64
|
|
|
63
65
|
sig { params(file_name: String).returns(RuboCop::AST::Node) }
|
|
64
66
|
def get_file_ast(file_name)
|
|
65
|
-
@file_ast_cache[file_name] ||=
|
|
67
|
+
@file_ast_cache[file_name] ||= begin
|
|
68
|
+
source = processed_source(ruby_source(file_name))
|
|
69
|
+
warn_unparseable(file_name, source) unless source.valid_syntax?
|
|
70
|
+
|
|
71
|
+
# The AST is also nil for source with no code, like a template that's only HTML
|
|
72
|
+
source.ast || ast_from('x')
|
|
73
|
+
end
|
|
66
74
|
end
|
|
67
75
|
|
|
68
76
|
sig { params(file_name: String).returns(String) }
|
|
69
77
|
def get_file(file_name)
|
|
70
|
-
@file_cache[file_name] ||= if RUBY_FILE.match?(file_name) && File.exist?(file_name)
|
|
78
|
+
@file_cache[file_name] ||= if (RUBY_FILE.match?(file_name) || ERB_FILE.match?(file_name)) && File.exist?(file_name)
|
|
71
79
|
File.read(file_name)
|
|
72
80
|
else
|
|
73
81
|
'x'
|
|
@@ -84,7 +92,7 @@ module QueryPackwerk
|
|
|
84
92
|
absolute_const_node = ast_from(class_name)
|
|
85
93
|
relative_const_node = ast_from(class_name.delete_prefix('::'))
|
|
86
94
|
|
|
87
|
-
@file_const_cache[const_key] = get_file_ast(file_name).
|
|
95
|
+
@file_const_cache[const_key] = get_file_ast(file_name).each_node.select do |node|
|
|
88
96
|
next false unless node.const_type?
|
|
89
97
|
|
|
90
98
|
node == absolute_const_node || node == relative_const_node
|
|
@@ -133,10 +141,32 @@ module QueryPackwerk
|
|
|
133
141
|
|
|
134
142
|
private
|
|
135
143
|
|
|
144
|
+
# Blanks out everything in an ERB template except its Ruby code, so line numbers still match the template
|
|
145
|
+
sig { params(file_name: String).returns(String) }
|
|
146
|
+
def ruby_source(file_name)
|
|
147
|
+
source = get_file(file_name)
|
|
148
|
+
return source unless ERB_FILE.match?(file_name)
|
|
149
|
+
|
|
150
|
+
Herb.extract_ruby(source, semicolons: true, comments: false, preserve_positions: true)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
sig { params(string: String).returns(RuboCop::ProcessedSource) }
|
|
154
|
+
def processed_source(string)
|
|
155
|
+
RuboCop::ProcessedSource.new(string, RUBY_VERSION.to_f)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
sig { params(file_name: String, source: RuboCop::ProcessedSource).void }
|
|
159
|
+
def warn_unparseable(file_name, source)
|
|
160
|
+
error = source.diagnostics.find { |diagnostic| diagnostic.level == :error }
|
|
161
|
+
location = error ? "#{file_name}:#{error.location.line} (#{error.message})" : file_name
|
|
162
|
+
|
|
163
|
+
warn "Could not parse #{location}, so its violations are not included"
|
|
164
|
+
end
|
|
165
|
+
|
|
136
166
|
# Turns a string into a Ruby AST
|
|
137
167
|
sig { params(string: String).returns(RuboCop::AST::Node) }
|
|
138
168
|
def ast_from(string)
|
|
139
|
-
|
|
169
|
+
processed_source(string).ast
|
|
140
170
|
end
|
|
141
171
|
|
|
142
172
|
# We can find a constant, but by going up its parents we can find the full call chain.
|
|
@@ -9,8 +9,6 @@ module QueryPackwerk
|
|
|
9
9
|
class Violation
|
|
10
10
|
extend T::Sig
|
|
11
11
|
|
|
12
|
-
# This does not play nicely with ERB files which may have violations
|
|
13
|
-
RUBY_FILE = T.let(/\.(rb|rake)\z/, Regexp)
|
|
14
12
|
ALL_CAPS = T.let(/\A[A-Z_]+\z/, Regexp)
|
|
15
13
|
|
|
16
14
|
sig { returns(QueryPackwerk::Package) }
|
|
@@ -168,13 +166,15 @@ module QueryPackwerk
|
|
|
168
166
|
load_cache!
|
|
169
167
|
|
|
170
168
|
file_sources = files.flat_map do |file_name|
|
|
169
|
+
lines = @file_cache.get_file(file_name).lines
|
|
170
|
+
|
|
171
171
|
@file_cache.get_full_sources(file_name: file_name, class_name: class_name).map do |s|
|
|
172
172
|
line_number = s.loc.line
|
|
173
|
-
start_pos = line_number - start_offset
|
|
174
|
-
end_pos = line_number + end_offset
|
|
173
|
+
start_pos = [line_number - start_offset, 1].max
|
|
174
|
+
end_pos = [line_number + end_offset, lines.size].min
|
|
175
175
|
|
|
176
176
|
location = "#{file_name}:#{s.loc.line} (L#{start_pos}..#{end_pos})"
|
|
177
|
-
context =
|
|
177
|
+
context = lines[(start_pos - 1)...end_pos]
|
|
178
178
|
full_context = unindent((context || ['']).join)
|
|
179
179
|
|
|
180
180
|
[@file_cache.anonymize_arguments(s.source), "> #{location}\n\n#{full_context}"]
|
|
@@ -192,7 +192,9 @@ module QueryPackwerk
|
|
|
192
192
|
def sources_with_contexts(start_offset: 3, end_offset: 3)
|
|
193
193
|
load_sources!
|
|
194
194
|
|
|
195
|
-
deep_merge_hash_groups(@original_collection)
|
|
195
|
+
deep_merge_hash_groups(@original_collection) do |v|
|
|
196
|
+
[v.class_name, v.sources_with_contexts(start_offset:, end_offset:)]
|
|
197
|
+
end
|
|
196
198
|
end
|
|
197
199
|
|
|
198
200
|
sig { params(start_offset: Integer, end_offset: Integer).returns(String) }
|
data/lib/query_packwerk.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: query_packwerk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.26
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gusto Engineering
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: herb
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.9'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.9'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: packwerk
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|