appmap 0.28.0 → 0.28.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: d94a20303fe329af9dfa6f4a0d4b14666a7eb25cba58d0ea6ede64b5991e85f9
4
- data.tar.gz: c441d6ee26453338fa449fed7762a0768155eaa934168c2245c47a5deb78cb38
3
+ metadata.gz: 8619a5924ba51ee48d76ebfe5c72030629c5338217b4fe659cd0a580eaa6ddb9
4
+ data.tar.gz: 0d8b1e8fcd41e0785b362350a53c95c5bc0ba5c628371b7b6216315b7ddcd85e
5
5
  SHA512:
6
- metadata.gz: a66524169eeb5e8d78974a8ac37122f52d5e2285cb4ff6f88f58947e8016d2b4ac458430df07a5b4e9c5ab37fdc7122bb887c694e375a7013bc8f34bf1b6b6b2
7
- data.tar.gz: 665354eca628d2d0f68706cf297667b9b3392a43e6dc364923f1f45f5316a6d3db54dea2d1e75ae83cd53c3ed9cb40ecc3794c10c9d6ee1c310aeed6710bb931
6
+ metadata.gz: c4da2cadb6a852b1213d1938b035ca147a939e7dc1378ef435d1e8b4d42d6f5b98e19191ecd2e1d1e48493817117123e0b9167080308dcc9ea5527bb676f436b
7
+ data.tar.gz: 04c2a36c913a3eec42dcd8aa61e789b9b91fed1e43b4bfe84729c6a7b4451fb1064c6efdba39e3818674df8f9560caa486e1d4c8170f04682938775fbb2c4d7e
@@ -1,3 +1,10 @@
1
+ # v0.28.1
2
+ * Fix the `defined_class` recorded in an appmap for an instance method included in a class
3
+ at runtime.
4
+
5
+ * Only include the `static` attribute on `call` events in an appmap. Determine its value
6
+ based on the receiver of the method call.
7
+
1
8
  # v0.28.0
2
9
 
3
10
  * Change behavior of **AppMap.record** to return a complete AppMap as a Hash.
@@ -74,10 +74,11 @@ module AppMap
74
74
 
75
75
  class_name_func = ->(event) { event['defined_class'] }
76
76
  full_name_func = lambda do |event|
77
+ call = event['event'] == 'call'
77
78
  class_name = event['defined_class']
78
79
  static = event['static']
79
80
  function_name = event['method_id']
80
- [ class_name, static ? '.' : '#', function_name ].join if class_name && !static.nil? && function_name
81
+ [ class_name, static ? '.' : '#', function_name ].join if call && class_name && !static.nil? && function_name
81
82
  end
82
83
 
83
84
  class_frequency = frequency_calc.call(class_name_func)
@@ -95,7 +95,7 @@ module AppMap
95
95
  location_file, lineno = location
96
96
  location_file = location_file[Dir.pwd.length + 1..-1] if location_file.index(Dir.pwd) == 0
97
97
 
98
- static = method.method.owner.singleton_class?
98
+ static = method.static
99
99
 
100
100
  object_infos = [
101
101
  {
@@ -15,15 +15,13 @@ module AppMap
15
15
  end
16
16
  end
17
17
 
18
- MethodEventStruct = Struct.new(:id, :event, :defined_class, :method_id, :path, :lineno, :static, :thread_id)
18
+ MethodEventStruct = Struct.new(:id, :event, :defined_class, :method_id, :path, :lineno, :thread_id)
19
19
 
20
20
  class MethodEvent < MethodEventStruct
21
21
  LIMIT = 100
22
22
 
23
23
  class << self
24
24
  def build_from_invocation(me, event_type, defined_class, method)
25
- singleton = method.owner.singleton_class?
26
-
27
25
  me.id = AppMap::Event.next_id_counter
28
26
  me.event = event_type
29
27
  me.defined_class = defined_class
@@ -32,7 +30,6 @@ module AppMap
32
30
  path = path[Dir.pwd.length + 1..-1] if path.index(Dir.pwd) == 0
33
31
  me.path = path
34
32
  me.lineno = method.source_location[1]
35
- me.static = singleton
36
33
  me.thread_id = Thread.current.object_id
37
34
  end
38
35
 
@@ -62,11 +59,10 @@ module AppMap
62
59
  end
63
60
  end
64
61
 
65
- alias static? static
66
62
  end
67
63
 
68
64
  class MethodCall < MethodEvent
69
- attr_accessor :parameters, :receiver
65
+ attr_accessor :parameters, :receiver, :static
70
66
 
71
67
  class << self
72
68
  def build_from_invocation(mc = MethodCall.new, defined_class, method, receiver, arguments)
@@ -88,6 +84,7 @@ module AppMap
88
84
  object_id: receiver.__id__,
89
85
  value: display_string(receiver)
90
86
  }
87
+ mc.static = receiver.is_a?(Module)
91
88
  MethodEvent.build_from_invocation(mc, :call, defined_class, method)
92
89
  end
93
90
  end
@@ -95,10 +92,13 @@ module AppMap
95
92
 
96
93
  def to_h
97
94
  super.tap do |h|
95
+ h[:static] = static
98
96
  h[:parameters] = parameters
99
97
  h[:receiver] = receiver
100
98
  end
101
99
  end
100
+
101
+ alias static? static
102
102
  end
103
103
 
104
104
  class MethodReturnIgnoreValue < MethodEvent
@@ -106,15 +106,24 @@ module AppMap
106
106
  # Skip methods that have no instruction sequence, as they are obviously trivial.
107
107
  next unless disasm
108
108
 
109
- defined_class, method_symbol = \
110
- if method.owner.singleton_class?
111
- # Singleton class name is like: #<Class:<(.*)>>
112
- class_name = method.owner.to_s['#<Class:<'.length-1..-2]
113
- [ class_name, '.' ]
114
- else
115
- [ method.owner.name, '#' ]
116
- end
117
-
109
+ defined_class, method_symbol = if method.owner.singleton_class?
110
+ # Singleton class names can take two forms:
111
+ # #<Class:Foo> or
112
+ # #<Class:#<Bar:0x0123ABC>>. Retrieve the name of
113
+ # the class from the string.
114
+ #
115
+ # (There really isn't a better way to do this. The
116
+ # singleton's reference to the class it was created
117
+ # from is stored in an instance variable named
118
+ # '__attached__'. It doesn't have the '@' prefix, so
119
+ # it's internal only, and not accessible from user
120
+ # code.)
121
+ class_name = /#<Class:((#<(?<cls>.*?):)|((?<cls>.*?)>))/.match(method.owner.to_s)['cls']
122
+ [ class_name, '.' ]
123
+ else
124
+ [ method.owner.name, '#' ]
125
+ end
126
+
118
127
  method_display_name = "#{defined_class}#{method_symbol}#{method.name}"
119
128
  # Don't try and trace the tracing method or there will be a stack overflow
120
129
  # in the defined hook method.
@@ -146,11 +155,11 @@ module AppMap
146
155
  end
147
156
  end
148
157
  end
149
- end
150
-
151
- instance_methods.each(&hook_method.call(cls))
152
- class_methods.each(&hook_method.call(cls.singleton_class))
153
158
  end
159
+
160
+ instance_methods.each(&hook_method.call(cls))
161
+ class_methods.each(&hook_method.call(cls.singleton_class))
162
+ end
154
163
  end
155
164
  end
156
165
  end
@@ -20,7 +20,7 @@ module AppMap
20
20
  attr_accessor :payload
21
21
 
22
22
  def initialize(path, lineno, payload)
23
- super AppMap::Event.next_id_counter, :call, HTTPServerRequest, :call, path, lineno, false, Thread.current.object_id
23
+ super AppMap::Event.next_id_counter, :call, HTTPServerRequest, :call, path, lineno, Thread.current.object_id
24
24
 
25
25
  self.payload = payload
26
26
  end
@@ -60,7 +60,7 @@ module AppMap
60
60
  attr_accessor :payload
61
61
 
62
62
  def initialize(path, lineno, payload, parent_id, elapsed)
63
- super AppMap::Event.next_id_counter, :return, HTTPServerResponse, :call, path, lineno, false, Thread.current.object_id
63
+ super AppMap::Event.next_id_counter, :return, HTTPServerResponse, :call, path, lineno, Thread.current.object_id
64
64
 
65
65
  self.payload = payload
66
66
  self.parent_id = parent_id
@@ -9,7 +9,7 @@ module AppMap
9
9
  attr_accessor :payload
10
10
 
11
11
  def initialize(path, lineno, payload)
12
- super AppMap::Event.next_id_counter, :call, SQLHandler, :call, path, lineno, false, Thread.current.object_id
12
+ super AppMap::Event.next_id_counter, :call, SQLHandler, :call, path, lineno, Thread.current.object_id
13
13
 
14
14
  self.payload = payload
15
15
  end
@@ -30,7 +30,7 @@ module AppMap
30
30
 
31
31
  class SQLReturn < AppMap::Event::MethodReturnIgnoreValue
32
32
  def initialize(path, lineno, parent_id, elapsed)
33
- super AppMap::Event.next_id_counter, :return, SQLHandler, :call, path, lineno, false, Thread.current.object_id
33
+ super AppMap::Event.next_id_counter, :return, SQLHandler, :call, path, lineno, Thread.current.object_id
34
34
 
35
35
  self.parent_id = parent_id
36
36
  self.elapsed = elapsed
@@ -2,7 +2,7 @@
2
2
 
3
3
  module AppMap
4
4
  module Trace
5
- ScopedMethod = Struct.new(:defined_class, :method)
5
+ ScopedMethod = Struct.new(:defined_class, :method, :static)
6
6
 
7
7
  class Tracing
8
8
  def initialize
@@ -67,7 +67,7 @@ module AppMap
67
67
  return unless @enabled
68
68
 
69
69
  @events << event
70
- @methods << Trace::ScopedMethod.new(defined_class, method) if defined_class && method
70
+ @methods << Trace::ScopedMethod.new(defined_class, method, event.static) if (defined_class && method && event.event == :call)
71
71
  end
72
72
 
73
73
  # Gets a unique list of the methods that were invoked by the program.
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.28.0'
6
+ VERSION = '0.28.1'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.2'
9
9
  end
@@ -551,9 +551,9 @@
551
551
  }
552
552
  },
553
553
  "lodash": {
554
- "version": "4.17.15",
555
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
556
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
554
+ "version": "4.17.19",
555
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
556
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
557
557
  },
558
558
  "longest": {
559
559
  "version": "1.0.1",
@@ -52,8 +52,8 @@ describe 'AbstractControllerBase' do
52
52
  method_id: build_user
53
53
  path: app/controllers/api/users_controller.rb
54
54
  lineno: 23
55
- static: false
56
55
  thread_id: .*
56
+ static: false
57
57
  parameters:
58
58
  - name: params
59
59
  class: Hash
@@ -57,8 +57,8 @@ describe 'AbstractControllerBase' do
57
57
  method_id: build_user
58
58
  path: app/controllers/api/users_controller.rb
59
59
  lineno: 23
60
- static: false
61
60
  thread_id: .*
61
+ static: false
62
62
  parameters:
63
63
  - name: params
64
64
  class: ActiveSupport::HashWithIndifferentAccess
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SingletonMethod
4
+ class << self
5
+ def say_default
6
+ 'default'
7
+ end
8
+ end
9
+
10
+ def SingletonMethod.say_class_defined
11
+ 'defined with explicit class scope'
12
+ end
13
+
14
+ def self.say_self_defined
15
+ 'defined with self class scope'
16
+ end
17
+
18
+ # When called, do_include calls +include+ to bring in the module
19
+ # AddMethod. AddMethod defines a new instance method, which gets
20
+ # added to the singleton class of SingletonMethod.
21
+ def do_include
22
+ class << self
23
+ SingletonMethod.include(AddMethod)
24
+ end
25
+ self
26
+ end
27
+
28
+ def self.new_with_instance_method
29
+ SingletonMethod.new.tap do |m|
30
+ def m.say_instance_defined
31
+ 'defined for an instance'
32
+ end
33
+ end
34
+ end
35
+
36
+ def to_s
37
+ 'Singleton Method fixture'
38
+ end
39
+ end
40
+
41
+ module AddMethod
42
+ def self.included(base)
43
+ base.module_eval do
44
+ define_method "added_method" do
45
+ _added_method
46
+ end
47
+ end
48
+ end
49
+
50
+ def _added_method
51
+ 'defined by including a module'
52
+ end
53
+ end
54
+
@@ -5,6 +5,16 @@ require 'appmap/hook'
5
5
  require 'appmap/event'
6
6
  require 'diffy'
7
7
 
8
+ # Show nulls as the literal +null+, rather than just leaving the field
9
+ # empty. This make some of the expected YAML below easier to
10
+ # understand.
11
+ module ShowYamlNulls
12
+ def visit_NilClass(o)
13
+ @emitter.scalar('null', nil, 'tag:yaml.org,2002:null', true, false, Psych::Nodes::Scalar::ANY)
14
+ end
15
+ end
16
+ Psych::Visitors::YAMLTree.prepend(ShowYamlNulls)
17
+
8
18
  describe 'AppMap class Hooking' do
9
19
  def collect_events(tracer)
10
20
  [].tap do |events|
@@ -30,26 +40,28 @@ describe 'AppMap class Hooking' do
30
40
  end.to_yaml
31
41
  end
32
42
 
33
- def invoke_test_file(file, &block)
43
+ def invoke_test_file(file, setup: nil, &block)
34
44
  AppMap.configuration = nil
35
45
  package = AppMap::Hook::Package.new(file, [])
36
46
  config = AppMap::Hook::Config.new('hook_spec', [ package ])
37
47
  AppMap.configuration = config
38
48
  AppMap::Hook.hook(config)
49
+
50
+ setup_result = setup.call if setup
39
51
 
40
52
  tracer = AppMap.tracing.trace
41
53
  AppMap::Event.reset_id_counter
42
54
  begin
43
55
  load file
44
- yield
56
+ yield setup_result
45
57
  ensure
46
58
  AppMap.tracing.delete(tracer)
47
59
  end
48
60
  [ config, tracer ]
49
61
  end
50
62
 
51
- def test_hook_behavior(file, events_yaml, &block)
52
- config, tracer = invoke_test_file(file, &block)
63
+ def test_hook_behavior(file, events_yaml, setup: nil, &block)
64
+ config, tracer = invoke_test_file(file, setup: setup, &block)
53
65
 
54
66
  events = collect_events(tracer)
55
67
  expect(Diffy::Diff.new(events, events_yaml).to_s).to eq('')
@@ -208,7 +220,7 @@ describe 'AppMap class Hooking' do
208
220
  :parameters:
209
221
  - :name: :kw
210
222
  :class: NilClass
211
- :value:
223
+ :value: null
212
224
  :kind: :key
213
225
  :receiver:
214
226
  :class: InstanceMethod
@@ -238,7 +250,7 @@ describe 'AppMap class Hooking' do
238
250
  :parameters:
239
251
  - :name: :block
240
252
  :class: NilClass
241
- :value:
253
+ :value: null
242
254
  :kind: :block
243
255
  :receiver:
244
256
  :class: InstanceMethod
@@ -260,15 +272,15 @@ describe 'AppMap class Hooking' do
260
272
  ---
261
273
  - :id: 1
262
274
  :event: :call
263
- :defined_class: ClassMethod
275
+ :defined_class: SingletonMethod
264
276
  :method_id: say_default
265
- :path: spec/fixtures/hook/class_method.rb
277
+ :path: spec/fixtures/hook/singleton_method.rb
266
278
  :lineno: 5
267
279
  :static: true
268
280
  :parameters: []
269
281
  :receiver:
270
282
  :class: Class
271
- :value: ClassMethod
283
+ :value: SingletonMethod
272
284
  - :id: 2
273
285
  :event: :return
274
286
  :parent_id: 1
@@ -276,8 +288,8 @@ describe 'AppMap class Hooking' do
276
288
  :class: String
277
289
  :value: default
278
290
  YAML
279
- test_hook_behavior 'spec/fixtures/hook/class_method.rb', events_yaml do
280
- expect(ClassMethod.say_default).to eq('default')
291
+ test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
292
+ expect(SingletonMethod.say_default).to eq('default')
281
293
  end
282
294
  end
283
295
 
@@ -286,15 +298,15 @@ describe 'AppMap class Hooking' do
286
298
  ---
287
299
  - :id: 1
288
300
  :event: :call
289
- :defined_class: ClassMethod
301
+ :defined_class: SingletonMethod
290
302
  :method_id: say_class_defined
291
- :path: spec/fixtures/hook/class_method.rb
303
+ :path: spec/fixtures/hook/singleton_method.rb
292
304
  :lineno: 10
293
305
  :static: true
294
306
  :parameters: []
295
307
  :receiver:
296
308
  :class: Class
297
- :value: ClassMethod
309
+ :value: SingletonMethod
298
310
  - :id: 2
299
311
  :event: :return
300
312
  :parent_id: 1
@@ -302,8 +314,8 @@ describe 'AppMap class Hooking' do
302
314
  :class: String
303
315
  :value: defined with explicit class scope
304
316
  YAML
305
- test_hook_behavior 'spec/fixtures/hook/class_method.rb', events_yaml do
306
- expect(ClassMethod.say_class_defined).to eq('defined with explicit class scope')
317
+ test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
318
+ expect(SingletonMethod.say_class_defined).to eq('defined with explicit class scope')
307
319
  end
308
320
  end
309
321
 
@@ -312,15 +324,15 @@ describe 'AppMap class Hooking' do
312
324
  ---
313
325
  - :id: 1
314
326
  :event: :call
315
- :defined_class: ClassMethod
327
+ :defined_class: SingletonMethod
316
328
  :method_id: say_self_defined
317
- :path: spec/fixtures/hook/class_method.rb
329
+ :path: spec/fixtures/hook/singleton_method.rb
318
330
  :lineno: 14
319
331
  :static: true
320
332
  :parameters: []
321
333
  :receiver:
322
334
  :class: Class
323
- :value: ClassMethod
335
+ :value: SingletonMethod
324
336
  - :id: 2
325
337
  :event: :return
326
338
  :parent_id: 1
@@ -328,11 +340,77 @@ describe 'AppMap class Hooking' do
328
340
  :class: String
329
341
  :value: defined with self class scope
330
342
  YAML
331
- test_hook_behavior 'spec/fixtures/hook/class_method.rb', events_yaml do
332
- expect(ClassMethod.say_self_defined).to eq('defined with self class scope')
343
+ test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
344
+ expect(SingletonMethod.say_self_defined).to eq('defined with self class scope')
333
345
  end
334
346
  end
335
347
 
348
+
349
+ it 'hooks an included method' do
350
+ events_yaml = <<~YAML
351
+ ---
352
+ - :id: 1
353
+ :event: :call
354
+ :defined_class: SingletonMethod
355
+ :method_id: added_method
356
+ :path: spec/fixtures/hook/singleton_method.rb
357
+ :lineno: 44
358
+ :static: false
359
+ :parameters: []
360
+ :receiver:
361
+ :class: SingletonMethod
362
+ :value: Singleton Method fixture
363
+ - :id: 2
364
+ :event: :call
365
+ :defined_class: AddMethod
366
+ :method_id: _added_method
367
+ :path: spec/fixtures/hook/singleton_method.rb
368
+ :lineno: 50
369
+ :static: false
370
+ :parameters: []
371
+ :receiver:
372
+ :class: SingletonMethod
373
+ :value: Singleton Method fixture
374
+ - :id: 3
375
+ :event: :return
376
+ :parent_id: 2
377
+ :return_value:
378
+ :class: String
379
+ :value: defined by including a module
380
+ - :id: 4
381
+ :event: :return
382
+ :parent_id: 1
383
+ :return_value:
384
+ :class: String
385
+ :value: defined by including a module
386
+ YAML
387
+
388
+ load 'spec/fixtures/hook/singleton_method.rb'
389
+ setup = -> { SingletonMethod.new.do_include }
390
+ test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml, setup: setup do |s|
391
+ expect(s.added_method).to eq('defined by including a module')
392
+ end
393
+ end
394
+
395
+ it "doesn't hook a singleton method defined for an instance" do
396
+ # Ideally, Ruby would fire a TracePoint event when a singleton
397
+ # class gets created by defining a method on an instance. It
398
+ # currently doesn't, though, so there's no way for us to hook such
399
+ # a method.
400
+ #
401
+ # This example will fail if Ruby's behavior changes at some point
402
+ # in the future.
403
+ events_yaml = <<~YAML
404
+ --- []
405
+ YAML
406
+
407
+ load 'spec/fixtures/hook/singleton_method.rb'
408
+ setup = -> { SingletonMethod.new_with_instance_method }
409
+ test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml, setup: setup do |s|
410
+ expect(s.say_instance_defined).to eq('defined for an instance')
411
+ end
412
+ end
413
+
336
414
  it 'Reports exceptions' do
337
415
  events_yaml = <<~YAML
338
416
  ---
@@ -59,7 +59,7 @@ class CLITest < Minitest::Test
59
59
 
60
60
  Method frequency:
61
61
  ----------------
62
- 2 Main.say_hello
62
+ 1 Main.say_hello
63
63
  OUTPUT
64
64
  end
65
65
 
@@ -85,7 +85,7 @@ class CLITest < Minitest::Test
85
85
  "method_frequency": [
86
86
  {
87
87
  "name": "Main.say_hello",
88
- "count": 2
88
+ "count": 1
89
89
  }
90
90
  ]
91
91
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.0
4
+ version: 0.28.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-24 00:00:00.000000000 Z
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -304,10 +304,10 @@ files:
304
304
  - spec/abstract_controller_base_spec.rb
305
305
  - spec/config_spec.rb
306
306
  - spec/fixtures/hook/attr_accessor.rb
307
- - spec/fixtures/hook/class_method.rb
308
307
  - spec/fixtures/hook/constructor.rb
309
308
  - spec/fixtures/hook/exception_method.rb
310
309
  - spec/fixtures/hook/instance_method.rb
310
+ - spec/fixtures/hook/singleton_method.rb
311
311
  - spec/fixtures/rack_users_app/.dockerignore
312
312
  - spec/fixtures/rack_users_app/.gitignore
313
313
  - spec/fixtures/rack_users_app/Dockerfile
@@ -471,7 +471,6 @@ files:
471
471
  - test/fixtures/cucumber4_recorder/features/support/hooks.rb
472
472
  - test/fixtures/cucumber4_recorder/features/support/steps.rb
473
473
  - test/fixtures/cucumber4_recorder/lib/hello.rb
474
- - test/fixtures/cucumber_recorder/.bundle/config
475
474
  - test/fixtures/cucumber_recorder/Gemfile
476
475
  - test/fixtures/cucumber_recorder/appmap.yml
477
476
  - test/fixtures/cucumber_recorder/features/say_hello.feature
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ClassMethod
4
- class << self
5
- def say_default
6
- 'default'
7
- end
8
- end
9
-
10
- def ClassMethod.say_class_defined
11
- 'defined with explicit class scope'
12
- end
13
-
14
- def self.say_self_defined
15
- 'defined with self class scope'
16
- end
17
- end