bade 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 202b283306b0a05d870766ff8d7c17f8312727843632958adb2bb3f2300a673f
4
- data.tar.gz: '0820f4f77eb7936b77748257faa1fd4ee51b206d4a7929c656f717127c7b2248'
3
+ metadata.gz: 9363fa63bbc18e9d9cb2af336438820127d766ef7e5b18306ddc37cdd608adfd
4
+ data.tar.gz: 6a6c86dea0211e852507fa26e7ec2d6d35b5b03469f5c6919455749134f102bd
5
5
  SHA512:
6
- metadata.gz: ecd2dbf7aa570c8051a2e1b59a1a537583cd2cd5005bb06328795de099fab4213a9cfd616a788d66e333a862253d6aecedd928632e3edb923f021e86658f6780
7
- data.tar.gz: 8633aba2120eaf8f60f96a357cde8eda8c32d862e92dca3c060f66c014bf1031e5bc2916077ee1d1a7de6494cc62c426ded062065c664949acaf849fce71de66
6
+ metadata.gz: 37b06b4ef4aa918a88e96c5bfd164ef5d41b9bc0e22949d857b3af143e6dcb462d41f8c10e880f29f4a201e0ca115309e4734e46268f0b1c6fc9f0c7c50802d2
7
+ data.tar.gz: a828c7d9c09450235b719c37381add83dcd0980d256f97b755dd6b5ceb287a1f6baca4f43a04c00523cf45a1d692aac6d7b7abd79f8b5694fe713f3686ceefa0
data/Bade.gemspec CHANGED
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  lib = File.expand_path('lib', __dir__)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'utils/where'
4
+
3
5
  module Bade
4
6
  module Runtime
5
7
  # Tracks created global variables and constants in block.
@@ -10,9 +12,16 @@ module Bade
10
12
  # @return [Array<[Object, :Symbol]>]
11
13
  attr_accessor :caught_constants
12
14
 
13
- def initialize
15
+ # @return [Array<String>, nil]
16
+ attr_accessor :constants_location_prefixes
17
+
18
+ # @param [Array<String>, nil] constants_location_prefixes If given, only constants whose location starts with one
19
+ # of the prefixes will be removed. If nil, all constants
20
+ # will be removed.
21
+ def initialize(constants_location_prefixes: nil)
14
22
  @caught_variables = []
15
23
  @caught_constants = []
24
+ @constants_location_prefixes = constants_location_prefixes
16
25
  end
17
26
 
18
27
  # @yieldreturn [T]
@@ -43,8 +52,8 @@ module Bade
43
52
  end
44
53
 
45
54
  def clear_constants
46
- @caught_constants.each do |(obj, name)|
47
- obj.send(:remove_const, name) if obj.const_defined?(name)
55
+ _filtered_constants.each do |(obj, name)|
56
+ obj.send(:remove_const, name)
48
57
  end
49
58
  @caught_constants = []
50
59
  end
@@ -54,6 +63,26 @@ module Bade
54
63
  eval("#{name} = nil", binding, __FILE__, __LINE__)
55
64
  end
56
65
  end
66
+
67
+ # Filteres caught constants by location prefixes and returns ones that should be removed.
68
+ #
69
+ # @return [Array<[Object, :Symbol]>]
70
+ def _filtered_constants
71
+ @caught_constants.select do |(obj, name)|
72
+ next unless obj.const_defined?(name)
73
+ next true if constants_location_prefixes.nil?
74
+
75
+ konst = obj.const_get(name)
76
+ begin
77
+ location = Bade.where_is(konst)
78
+ rescue ::ArgumentError
79
+ next
80
+ end
81
+
82
+ path = location.first
83
+ constants_location_prefixes&.any? { |prefix| path.start_with?(prefix) }
84
+ end
85
+ end
57
86
  end
58
87
  end
59
88
  end
@@ -86,7 +86,7 @@ module Bade
86
86
  # @param [String] filename
87
87
  def __load(filename)
88
88
  # FakeFS does not fake `load` method
89
- if defined?(:FakeFS) && FakeFS.activated?
89
+ if Object.const_defined?(:FakeFS) && Object.const_get(:FakeFS).activated?
90
90
  # rubocop:disable Security/Eval
91
91
  eval(File.read(filename), __get_binding, filename)
92
92
  # rubocop:enable Security/Eval
@@ -98,7 +98,7 @@ module Bade
98
98
  # @param [String] filename
99
99
  def require_relative(filename)
100
100
  # FakeFS does not fake `require_relative` method
101
- if defined?(:FakeFS) && FakeFS.activated?
101
+ if Object.const_defined?(:FakeFS) && Object.const_get(:FakeFS).activated?
102
102
  # rubocop:disable Security/Eval
103
103
  eval(File.read(filename), __get_binding, filename)
104
104
  # rubocop:enable Security/Eval
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Inspired by https://gist.github.com/wtaysom/1236979
4
+
5
+ module Bade
6
+ module Where
7
+ class << self
8
+ def is_proc(proc)
9
+ source_location(proc)
10
+ end
11
+
12
+ def is_method(klass, method_name)
13
+ source_location(klass.method(method_name))
14
+ end
15
+
16
+ def is_instance_method(klass, method_name)
17
+ source_location(klass.instance_method(method_name))
18
+ end
19
+
20
+ def are_methods(klass, method_name)
21
+ are_via_extractor(:method, klass, method_name)
22
+ end
23
+
24
+ def are_instance_methods(klass, method_name)
25
+ are_via_extractor(:method, klass, method_name)
26
+ end
27
+
28
+ def is_class(klass)
29
+ defined_methods(klass)
30
+ .group_by { |sl| sl[0] }
31
+ .map do |file, sls|
32
+ lines = sls.map { |sl| sl[1] }
33
+ count = lines.size
34
+ line = lines.min
35
+
36
+ {
37
+ file: file,
38
+ count: count,
39
+ line: line
40
+ }
41
+ end
42
+ .sort_by { |fc| fc[:count] }
43
+ .map { |fc| [fc[:file], fc[:line]] }
44
+ end
45
+
46
+ # Raises ArgumentError if klass does not have any Ruby methods defined in it.
47
+ def is_class_primarily(klass)
48
+ source_locations = is_class(klass)
49
+ if source_locations.empty?
50
+ methods = defined_methods(klass)
51
+ msg = if methods.empty?
52
+ "#{klass} has no methods"
53
+ else
54
+ "#{klass} only has built-in methods (#{methods.size} in total)"
55
+ end
56
+
57
+ raise ::ArgumentError, msg
58
+ end
59
+ source_locations[0]
60
+ end
61
+
62
+ private
63
+
64
+ def source_location(method)
65
+ method.source_location || (
66
+ method.to_s =~ /: (.*)>/
67
+ Regexp.last_match(1)
68
+ )
69
+ end
70
+
71
+ def are_via_extractor(extractor, klass, method_name)
72
+ klass.ancestors
73
+ .map do |ancestor|
74
+ method = ancestor.send(extractor, method_name)
75
+ source_location(method) if method.owner == ancestor
76
+ end
77
+ .compact
78
+ end
79
+
80
+ def defined_methods(klass)
81
+ methods = klass.methods(false).map { |m| klass.method(m) } +
82
+ klass.instance_methods(false).map { |m| klass.instance_method(m) }
83
+ methods
84
+ .map(&:source_location)
85
+ .compact
86
+ end
87
+ end
88
+ end
89
+
90
+ def self.where_is(klass, method = nil)
91
+ if method
92
+ begin
93
+ Where.is_instance_method(klass, method)
94
+ rescue NameError
95
+ Where.is_method(klass, method)
96
+ end
97
+ else
98
+ Where.is_class_primarily(klass)
99
+ end
100
+ end
101
+ end
data/lib/bade/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bade
4
- VERSION = '0.3.0'.freeze
4
+ VERSION = '0.3.1'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Kříž
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-21 00:00:00.000000000 Z
11
+ date: 2022-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: psych
@@ -112,6 +112,7 @@ files:
112
112
  - lib/bade/runtime/globals_tracker.rb
113
113
  - lib/bade/runtime/mixin.rb
114
114
  - lib/bade/runtime/render_binding.rb
115
+ - lib/bade/runtime/utils/where.rb
115
116
  - lib/bade/version.rb
116
117
  homepage: https://github.com/epuber-io/bade
117
118
  licenses:
@@ -133,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements: []
136
- rubygems_version: 3.3.8
137
+ rubygems_version: 3.3.9
137
138
  signing_key:
138
139
  specification_version: 4
139
140
  summary: Minimalistic template engine for Ruby.