reek 1.2.7.3 → 1.2.8
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.
- data/History.txt +17 -0
- data/README.md +32 -48
- data/config/defaults.reek +7 -1
- data/features/api.feature +20 -0
- data/features/masking_smells.feature +41 -0
- data/features/options.feature +4 -0
- data/features/rake_task.feature +14 -0
- data/features/yaml.feature +8 -8
- data/lib/reek.rb +1 -1
- data/lib/reek/cli/command_line.rb +9 -2
- data/lib/reek/cli/reek_command.rb +5 -4
- data/lib/reek/cli/yaml_command.rb +2 -2
- data/lib/reek/core/code_context.rb +10 -1
- data/lib/reek/core/method_context.rb +2 -2
- data/lib/reek/core/sniffer.rb +3 -1
- data/lib/reek/core/stop_context.rb +4 -0
- data/lib/reek/examiner.rb +2 -2
- data/lib/reek/rake/task.rb +16 -0
- data/lib/reek/smell_warning.rb +3 -2
- data/lib/reek/smells/attribute.rb +13 -9
- data/lib/reek/smells/boolean_parameter.rb +14 -9
- data/lib/reek/smells/class_variable.rb +16 -5
- data/lib/reek/smells/control_couple.rb +11 -6
- data/lib/reek/smells/data_clump.rb +33 -30
- data/lib/reek/smells/duplication.rb +39 -8
- data/lib/reek/smells/feature_envy.rb +7 -8
- data/lib/reek/smells/irresponsible_module.rb +12 -3
- data/lib/reek/smells/large_class.rb +31 -15
- data/lib/reek/smells/long_method.rb +15 -5
- data/lib/reek/smells/long_parameter_list.rb +14 -7
- data/lib/reek/smells/long_yield_list.rb +12 -9
- data/lib/reek/smells/nested_iterators.rb +46 -11
- data/lib/reek/smells/simulated_polymorphism.rb +16 -8
- data/lib/reek/smells/smell_detector.rb +13 -13
- data/lib/reek/smells/uncommunicative_method_name.rb +12 -20
- data/lib/reek/smells/uncommunicative_module_name.rb +17 -19
- data/lib/reek/smells/uncommunicative_parameter_name.rb +22 -15
- data/lib/reek/smells/uncommunicative_variable_name.rb +24 -18
- data/lib/reek/smells/utility_function.rb +6 -6
- data/lib/reek/source/code_comment.rb +19 -1
- data/lib/reek/source/tree_dresser.rb +40 -22
- data/reek.gemspec +6 -4
- data/spec/matchers/smell_of_matcher.rb +58 -0
- data/spec/reek/core/code_context_spec.rb +4 -2
- data/spec/reek/core/code_parser_spec.rb +2 -1
- data/spec/reek/core/method_context_spec.rb +5 -5
- data/spec/reek/smells/attribute_spec.rb +2 -4
- data/spec/reek/smells/boolean_parameter_spec.rb +32 -42
- data/spec/reek/smells/class_variable_spec.rb +22 -6
- data/spec/reek/smells/control_couple_spec.rb +15 -14
- data/spec/reek/smells/data_clump_spec.rb +29 -111
- data/spec/reek/smells/duplication_spec.rb +79 -49
- data/spec/reek/smells/feature_envy_spec.rb +1 -2
- data/spec/reek/smells/irresponsible_module_spec.rb +43 -22
- data/spec/reek/smells/large_class_spec.rb +34 -59
- data/spec/reek/smells/long_method_spec.rb +15 -10
- data/spec/reek/smells/long_parameter_list_spec.rb +24 -24
- data/spec/reek/smells/long_yield_list_spec.rb +13 -14
- data/spec/reek/smells/nested_iterators_spec.rb +93 -76
- data/spec/reek/smells/smell_detector_shared.rb +4 -2
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +10 -27
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -23
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +36 -26
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +45 -48
- data/spec/reek/smells/utility_function_spec.rb +14 -13
- data/spec/reek/source/code_comment_spec.rb +61 -3
- data/spec/reek/source/tree_dresser_spec.rb +96 -1
- data/spec/samples/config/allow_duplication.reek +3 -0
- data/spec/samples/config/deeper_nested_iterators.reek +3 -0
- data/spec/samples/demo/demo.rb +8 -0
- data/spec/samples/inline_config/dirty.rb +16 -0
- data/spec/samples/inline_config/masked.reek +7 -0
- data/spec/samples/mask_some/dirty.rb +8 -0
- data/spec/samples/mask_some/some.reek +8 -0
- data/spec/spec_helper.rb +2 -0
- metadata +15 -5
data/History.txt
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
== 1.2.8 (2010-04-26)
|
2
|
+
|
3
|
+
=== Major Changes
|
4
|
+
* Smell detectors can be configured or disabled in code comments
|
5
|
+
** Comment with :reek:smell_name disables the named smell for a class, module or method
|
6
|
+
** Comment with :reek:smell_name:{...} for more detailed configuration
|
7
|
+
* Additional config file(s) can be specified:
|
8
|
+
** on the command-line using -c
|
9
|
+
** via Reek::Rake::Task in the rakefile
|
10
|
+
|
11
|
+
=== Minor Changes
|
12
|
+
* Duplication can be configured to ignore specific calls
|
13
|
+
* IrresponsibleModule now reports scoped module names correctly (#66)
|
14
|
+
* NestedIterators is now more configurable:
|
15
|
+
** Option to specify permitted nesting depth (#14)
|
16
|
+
** Option to ignore certain iterator methods
|
17
|
+
|
1
18
|
== 1.2.7.3 (2010-03-29)
|
2
19
|
|
3
20
|
=== Minor Changes
|
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Reek -- code smell detection for Ruby
|
2
|
-
=====================================
|
1
|
+
# Reek -- code smell detection for Ruby
|
3
2
|
|
4
3
|
Reek is a tool that examines Ruby classes, modules and methods and
|
5
4
|
reports any code smells it finds. Install it like this:
|
@@ -16,63 +15,47 @@ or run
|
|
16
15
|
|
17
16
|
$ reek --help
|
18
17
|
|
19
|
-
Example
|
20
|
-
|
21
|
-
|
22
|
-
Imagine a source file <tt>csv_writer.rb</tt> containing:
|
23
|
-
|
24
|
-
class CsvWriter
|
25
|
-
def write_line(fields)
|
26
|
-
if (fields.length == 0)
|
27
|
-
puts
|
28
|
-
else
|
29
|
-
write_field(fields[0])
|
30
|
-
1.upto(fields.length-1) do |i|
|
31
|
-
print ","
|
32
|
-
write_field(fields[i])
|
33
|
-
end
|
34
|
-
puts
|
35
|
-
end
|
36
|
-
end
|
18
|
+
## Example
|
19
|
+
|
20
|
+
Imagine a source file <tt>demo.rb</tt> containing:
|
37
21
|
|
38
|
-
|
22
|
+
class Dirty
|
23
|
+
# This method smells of :reek:NestedIterators but ignores them
|
24
|
+
def awful(x, y, offset = 0, log = false)
|
25
|
+
puts @screen.title
|
26
|
+
@screen = widgets.map {|w| w.each {|key| key += 3}}
|
27
|
+
puts @screen.contents
|
28
|
+
end
|
39
29
|
end
|
40
30
|
|
41
31
|
Reek will report the following code smells in this file:
|
42
32
|
|
43
|
-
$ reek
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
* [Long Parameter List](http://wiki.github.com/kevinrutherford/reek/long-parameter-list)
|
59
|
-
* [Simulated Polymorphism](http://wiki.github.com/kevinrutherford/reek/simulated-polymorphism)
|
60
|
-
* [Uncommunicative Name](http://wiki.github.com/kevinrutherford/reek/uncommunicative-name)
|
61
|
-
|
62
|
-
...and more. See the [Reek wiki](http://wiki.github.com/kevinrutherford/reek/code-smells)
|
33
|
+
$ reek demo.rb
|
34
|
+
spec/samples/demo/demo.rb -- 6 warnings:
|
35
|
+
Dirty has no descriptive comment (IrresponsibleModule)
|
36
|
+
Dirty#awful has 4 parameters (LongParameterList)
|
37
|
+
Dirty#awful has boolean parameter 'log' (ControlCouple)
|
38
|
+
Dirty#awful has the parameter name 'x' (UncommunicativeName)
|
39
|
+
Dirty#awful has the parameter name 'y' (UncommunicativeName)
|
40
|
+
Dirty#awful has the variable name 'w' (UncommunicativeName)
|
41
|
+
|
42
|
+
## Features
|
43
|
+
|
44
|
+
Reek currently includes checks for some aspects of Control Couple,
|
45
|
+
Data Clump, Feature Envy, Large Class, Long Method, Long Parameter List,
|
46
|
+
Simulated Polymorphism, Uncommunicative Name and more.
|
47
|
+
See the [Reek wiki](http://wiki.github.com/kevinrutherford/reek/code-smells)
|
63
48
|
for up to date details of exactly what Reek will check in your code.
|
64
49
|
|
65
|
-
Tool Integration
|
66
|
-
----------------
|
50
|
+
### Tool Integration
|
67
51
|
|
68
52
|
Reek integrates with many of your favourite tools:
|
69
53
|
|
70
|
-
*
|
71
|
-
*
|
54
|
+
* `require 'reek/rake/task'` to easily add Reek to your Rakefile
|
55
|
+
* `require 'reek/spec'` to add the `should_not reek` custom matcher to your Rspec examples
|
72
56
|
* Reek is fully compliant with Ruby 1.8.6, 1.8.7 and 1.9.1
|
73
57
|
|
74
|
-
Dependencies
|
75
|
-
------------
|
58
|
+
### Dependencies
|
76
59
|
|
77
60
|
Reek makes use of the following other gems:
|
78
61
|
|
@@ -86,5 +69,6 @@ Learn More
|
|
86
69
|
Find out more about Reek from any of the following sources:
|
87
70
|
|
88
71
|
* Browse the Reek documentation at [http://wiki.github.com/kevinrutherford/reek](http://wiki.github.com/kevinrutherford/reek)
|
89
|
-
* Browse the code or install the latest
|
72
|
+
* Browse the code or install the latest development version from [http://github.com/kevinrutherford/reek/tree](http://github.com/kevinrutherford/reek/tree)
|
90
73
|
* Read the code API at [http://rdoc.info/projects/kevinrutherford/reek](http://rdoc.info/projects/kevinrutherford/reek)
|
74
|
+
* Follow [@rubyreek](http://twitter.com/rubyreek) on twitter!
|
data/config/defaults.reek
CHANGED
@@ -56,14 +56,20 @@ UncommunicativeModuleName:
|
|
56
56
|
- !ruby/regexp /^.$/
|
57
57
|
- !ruby/regexp /[0-9]$/
|
58
58
|
NestedIterators:
|
59
|
-
|
59
|
+
ignore_iterators: []
|
60
|
+
|
61
|
+
exclude: []
|
62
|
+
|
60
63
|
enabled: true
|
64
|
+
max_allowed_nesting: 1
|
61
65
|
LongMethod:
|
62
66
|
max_statements: 5
|
63
67
|
exclude:
|
64
68
|
- initialize
|
65
69
|
enabled: true
|
66
70
|
Duplication:
|
71
|
+
allow_calls: []
|
72
|
+
|
67
73
|
exclude: []
|
68
74
|
|
69
75
|
enabled: true
|
@@ -0,0 +1,20 @@
|
|
1
|
+
@masking
|
2
|
+
Feature: The Reek API maintains backwards compatibility
|
3
|
+
In order to use Reek witthout fuss
|
4
|
+
As a developer
|
5
|
+
I want to mave a stable API
|
6
|
+
|
7
|
+
Scenario: the demo example reports as expected
|
8
|
+
When I run reek spec/samples/demo
|
9
|
+
Then the exit status indicates smells
|
10
|
+
And it reports:
|
11
|
+
"""
|
12
|
+
spec/samples/demo/demo.rb -- 6 warnings:
|
13
|
+
Dirty has no descriptive comment (IrresponsibleModule)
|
14
|
+
Dirty#awful has 4 parameters (LongParameterList)
|
15
|
+
Dirty#awful has boolean parameter 'log' (ControlCouple)
|
16
|
+
Dirty#awful has the parameter name 'x' (UncommunicativeName)
|
17
|
+
Dirty#awful has the parameter name 'y' (UncommunicativeName)
|
18
|
+
Dirty#awful has the variable name 'w' (UncommunicativeName)
|
19
|
+
|
20
|
+
"""
|
@@ -86,3 +86,44 @@ Feature: Masking smells using config files
|
|
86
86
|
Dirty#a calls puts(@s.title) twice (Duplication)
|
87
87
|
|
88
88
|
"""
|
89
|
+
|
90
|
+
Scenario: allow masking some calls for duplication smell
|
91
|
+
When I run reek spec/samples/mask_some/dirty.rb
|
92
|
+
Then the exit status indicates smells
|
93
|
+
And it reports:
|
94
|
+
"""
|
95
|
+
spec/samples/mask_some/dirty.rb -- 2 warnings:
|
96
|
+
Dirty#a calls @s.title twice (Duplication)
|
97
|
+
Dirty#a contains iterators nested 2 deep (NestedIterators)
|
98
|
+
|
99
|
+
"""
|
100
|
+
|
101
|
+
@comments
|
102
|
+
Scenario: provide extra masking inline in comments
|
103
|
+
When I run reek spec/samples/inline_config
|
104
|
+
Then the exit status indicates smells
|
105
|
+
And it reports:
|
106
|
+
"""
|
107
|
+
spec/samples/inline_config/dirty.rb -- 1 warning:
|
108
|
+
Dirty#a calls @s.title twice (Duplication)
|
109
|
+
|
110
|
+
"""
|
111
|
+
|
112
|
+
Scenario: supports a config file
|
113
|
+
When I run reek -c spec/samples/config/allow_duplication.reek spec/samples/masked/dirty.rb
|
114
|
+
Then the exit status indicates smells
|
115
|
+
And it reports:
|
116
|
+
"""
|
117
|
+
spec/samples/masked/dirty.rb -- 1 warning:
|
118
|
+
Dirty#a contains iterators nested 2 deep (NestedIterators)
|
119
|
+
|
120
|
+
"""
|
121
|
+
|
122
|
+
Scenario: supports multiple config files
|
123
|
+
When I run reek -c spec/samples/config/allow_duplication.reek -c spec/samples/config/deeper_nested_iterators.reek spec/samples/masked/dirty.rb
|
124
|
+
Then it succeeds
|
125
|
+
And it reports:
|
126
|
+
"""
|
127
|
+
spec/samples/masked/dirty.rb -- 0 warnings
|
128
|
+
|
129
|
+
"""
|
data/features/options.feature
CHANGED
@@ -35,6 +35,10 @@ Feature: Reek can be controlled using command-line options
|
|
35
35
|
-v, --version Show version
|
36
36
|
|
37
37
|
|
38
|
+
Configuration:
|
39
|
+
-c, --config FILE Read configuration options from FILE
|
40
|
+
|
41
|
+
|
38
42
|
Report formatting:
|
39
43
|
-q, --[no-]quiet Suppress headings for smell-free source files
|
40
44
|
-y, --yaml Report smells in YAML format
|
data/features/rake_task.feature
CHANGED
@@ -65,3 +65,17 @@ Feature: Reek can be driven through its Task
|
|
65
65
|
Dirty#a has the name 'a' (UncommunicativeName)
|
66
66
|
Dirty#a has the variable name 'x' (UncommunicativeName)
|
67
67
|
"""
|
68
|
+
|
69
|
+
Scenario: can be configured with config_files
|
70
|
+
When I run rake reek with:
|
71
|
+
"""
|
72
|
+
Reek::Rake::Task.new do |t|
|
73
|
+
t.config_files = 'spec/samples/config/**/*.reek'
|
74
|
+
t.source_files = 'spec/samples/masked/dirty.rb'
|
75
|
+
end
|
76
|
+
"""
|
77
|
+
Then it succeeds
|
78
|
+
And it reports:
|
79
|
+
"""
|
80
|
+
spec/samples/masked/dirty.rb -- 0 warnings
|
81
|
+
"""
|
data/features/yaml.feature
CHANGED
@@ -54,7 +54,7 @@ Feature: Report smells using simple YAML layout
|
|
54
54
|
smell:
|
55
55
|
class: NestedIterators
|
56
56
|
depth: 2
|
57
|
-
subclass:
|
57
|
+
subclass: NestedIterators
|
58
58
|
message: contains iterators nested 2 deep
|
59
59
|
status:
|
60
60
|
is_active: true
|
@@ -63,7 +63,7 @@ Feature: Report smells using simple YAML layout
|
|
63
63
|
|
64
64
|
@stdin
|
65
65
|
Scenario: return non-zero status when there are smells
|
66
|
-
When I pass "
|
66
|
+
When I pass "class Turn; end" to reek --yaml
|
67
67
|
Then the exit status indicates smells
|
68
68
|
And it reports:
|
69
69
|
"""
|
@@ -71,14 +71,14 @@ Feature: Report smells using simple YAML layout
|
|
71
71
|
- !ruby/object:Reek::SmellWarning
|
72
72
|
location:
|
73
73
|
lines:
|
74
|
-
-
|
75
|
-
context: Turn
|
74
|
+
- 1
|
75
|
+
context: Turn
|
76
76
|
source: $stdin
|
77
77
|
smell:
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
message: has
|
78
|
+
class: IrresponsibleModule
|
79
|
+
subclass: IrresponsibleModule
|
80
|
+
module_name: Turn
|
81
|
+
message: has no descriptive comment
|
82
82
|
status:
|
83
83
|
is_active: true
|
84
84
|
|
data/lib/reek.rb
CHANGED
@@ -19,6 +19,7 @@ module Reek
|
|
19
19
|
@parser = OptionParser.new
|
20
20
|
@report_class = VerboseReport
|
21
21
|
@command_class = ReekCommand
|
22
|
+
@config_files = []
|
22
23
|
set_options
|
23
24
|
end
|
24
25
|
|
@@ -35,6 +36,7 @@ module Reek
|
|
35
36
|
# reek -v|--version Output the tool's version number
|
36
37
|
#
|
37
38
|
# reek [options] files List the smells in the given files
|
39
|
+
# -c|--config file Specify file(s) with config options
|
38
40
|
# -q|-[no-]quiet Only list files that have smells
|
39
41
|
# files Names of files or dirs to be checked
|
40
42
|
#
|
@@ -62,6 +64,11 @@ EOB
|
|
62
64
|
@command_class = VersionCommand
|
63
65
|
end
|
64
66
|
|
67
|
+
@parser.separator "\nConfiguration:"
|
68
|
+
@parser.on("-c", "--config FILE", "Read configuration options from FILE") do |file|
|
69
|
+
@config_files << file
|
70
|
+
end
|
71
|
+
|
65
72
|
@parser.separator "\nReport formatting:"
|
66
73
|
@parser.on("-q", "--[no-]quiet", "Suppress headings for smell-free source files") do |opt|
|
67
74
|
@report_class = opt ? QuietReport : VerboseReport
|
@@ -82,10 +89,10 @@ EOB
|
|
82
89
|
VersionCommand.new(@parser.program_name)
|
83
90
|
elsif @command_class == YamlCommand
|
84
91
|
sources = get_sources
|
85
|
-
YamlCommand.create(sources)
|
92
|
+
YamlCommand.create(sources, @config_files)
|
86
93
|
else
|
87
94
|
sources = get_sources
|
88
|
-
ReekCommand.create(sources, @report_class)
|
95
|
+
ReekCommand.create(sources, @report_class, @config_files)
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
@@ -8,19 +8,20 @@ module Reek
|
|
8
8
|
# text report format.
|
9
9
|
#
|
10
10
|
class ReekCommand
|
11
|
-
def self.create(sources, report_class)
|
12
|
-
new(report_class, sources)
|
11
|
+
def self.create(sources, report_class, config_files = [])
|
12
|
+
new(report_class, sources, config_files)
|
13
13
|
end
|
14
14
|
|
15
|
-
def initialize(report_class, sources)
|
15
|
+
def initialize(report_class, sources, config_files = [])
|
16
16
|
@sources = sources
|
17
17
|
@report_class = report_class
|
18
|
+
@config_files = config_files
|
18
19
|
end
|
19
20
|
|
20
21
|
def execute(view)
|
21
22
|
had_smells = false
|
22
23
|
@sources.each do |source|
|
23
|
-
examiner = Examiner.new(source)
|
24
|
+
examiner = Examiner.new(source, @config_files)
|
24
25
|
rpt = @report_class.new(examiner)
|
25
26
|
had_smells ||= examiner.smelly?
|
26
27
|
view.output(rpt.report)
|
@@ -8,8 +8,8 @@ module Reek
|
|
8
8
|
# YAML format.
|
9
9
|
#
|
10
10
|
class YamlCommand
|
11
|
-
def self.create(sources)
|
12
|
-
examiners = sources.map {|src| Examiner.new(src) }
|
11
|
+
def self.create(sources, config_files)
|
12
|
+
examiners = sources.map {|src| Examiner.new(src, config_files) }
|
13
13
|
new(examiners)
|
14
14
|
end
|
15
15
|
|
@@ -10,11 +10,12 @@ module Reek
|
|
10
10
|
#
|
11
11
|
class CodeContext
|
12
12
|
|
13
|
-
attr_reader :exp
|
13
|
+
attr_reader :exp, :config
|
14
14
|
|
15
15
|
def initialize(outer, exp)
|
16
16
|
@outer = outer
|
17
17
|
@exp = exp
|
18
|
+
@config = local_config
|
18
19
|
end
|
19
20
|
|
20
21
|
def name
|
@@ -50,6 +51,14 @@ module Reek
|
|
50
51
|
outer = @outer ? @outer.full_name : ''
|
51
52
|
exp.full_name(outer)
|
52
53
|
end
|
54
|
+
|
55
|
+
def local_config
|
56
|
+
return Hash.new if @exp.nil?
|
57
|
+
config = Source::CodeComment.new(@exp.comments || '').config
|
58
|
+
return config unless @outer
|
59
|
+
@outer.config.deep_copy.adopt!(config)
|
60
|
+
# no tests for this -----^
|
61
|
+
end
|
53
62
|
end
|
54
63
|
end
|
55
64
|
end
|
@@ -10,10 +10,10 @@ module Reek
|
|
10
10
|
module MethodParameters
|
11
11
|
def default_assignments
|
12
12
|
assignments = self[-1]
|
13
|
-
result =
|
13
|
+
result = []
|
14
14
|
return result unless is_assignment_block?(assignments)
|
15
15
|
assignments[1..-1].each do |exp|
|
16
|
-
result
|
16
|
+
result << exp[1..2] if exp[0] == :lasgn
|
17
17
|
end
|
18
18
|
result
|
19
19
|
end
|
data/lib/reek/core/sniffer.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'code_parser')
|
2
2
|
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'smells')
|
3
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'source', 'config_file')
|
3
4
|
require 'yaml'
|
4
5
|
|
5
6
|
#
|
@@ -64,12 +65,13 @@ module Reek
|
|
64
65
|
]
|
65
66
|
end
|
66
67
|
|
67
|
-
def initialize(src)
|
68
|
+
def initialize(src, config_files = [])
|
68
69
|
@typed_detectors = nil
|
69
70
|
@detectors = Hash.new
|
70
71
|
Sniffer.smell_classes.each do |klass|
|
71
72
|
@detectors[klass] = klass.new(src.desc)
|
72
73
|
end
|
74
|
+
config_files.each{ |cf| Reek::Source::ConfigFile.new(cf).configure(self) }
|
73
75
|
@source = src
|
74
76
|
src.configure(self)
|
75
77
|
end
|