ruby-lint 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.asc +17 -0
- data/.gitignore +1 -0
- data/.travis.yml +25 -0
- data/.yardopts +4 -0
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/MANIFEST +238 -49
- data/README.md +84 -131
- data/Rakefile +6 -0
- data/bin/ruby-lint +2 -2
- data/checksum/.gitkeep +0 -0
- data/doc/DCO.md +26 -0
- data/doc/architecture.md +63 -0
- data/doc/code_analysis.md +90 -0
- data/doc/configuration.md +86 -0
- data/doc/contributing.md +16 -0
- data/doc/graphviz/flow.dot +7 -0
- data/doc/images/.gitkeep +0 -0
- data/doc/images/flow.png +0 -0
- data/lib/ruby-lint.rb +35 -35
- data/lib/ruby-lint/analyze/argument_amount.rb +73 -0
- data/lib/ruby-lint/analyze/shadowing_variables.rb +19 -24
- data/lib/ruby-lint/analyze/undefined_methods.rb +68 -0
- data/lib/ruby-lint/analyze/undefined_variables.rb +42 -69
- data/lib/ruby-lint/analyze/unused_variables.rb +23 -78
- data/lib/ruby-lint/base.rb +85 -0
- data/lib/ruby-lint/cli.rb +23 -167
- data/lib/ruby-lint/cli/analyze.rb +99 -0
- data/lib/ruby-lint/cli/ast.rb +35 -0
- data/lib/ruby-lint/cli/base.rb +120 -0
- data/lib/ruby-lint/configuration.rb +112 -0
- data/lib/ruby-lint/constant_loader.rb +92 -0
- data/lib/ruby-lint/definition/ruby_method.rb +248 -0
- data/lib/ruby-lint/definition/ruby_object.rb +757 -0
- data/lib/ruby-lint/definition_generator.rb +155 -0
- data/lib/ruby-lint/definitions/core.rb +5 -0
- data/lib/ruby-lint/definitions/core/arg0.rb +7 -0
- data/lib/ruby-lint/definitions/core/argf.rb +7 -0
- data/lib/ruby-lint/definitions/core/argument_error.rb +12 -0
- data/lib/ruby-lint/definitions/core/argv.rb +7 -0
- data/lib/ruby-lint/definitions/core/array.rb +414 -0
- data/lib/ruby-lint/definitions/core/autoload.rb +39 -0
- data/lib/ruby-lint/definitions/core/basic_object.rb +46 -0
- data/lib/ruby-lint/definitions/core/bignum.rb +128 -0
- data/lib/ruby-lint/definitions/core/binding.rb +52 -0
- data/lib/ruby-lint/definitions/core/class.rb +23 -0
- data/lib/ruby-lint/definitions/core/comparable.rb +38 -0
- data/lib/ruby-lint/definitions/core/complex.rb +195 -0
- data/lib/ruby-lint/definitions/core/condition_variable.rb +19 -0
- data/lib/ruby-lint/definitions/core/continuation.rb +8 -0
- data/lib/ruby-lint/definitions/core/data.rb +8 -0
- data/lib/ruby-lint/definitions/core/date.rb +706 -0
- data/lib/ruby-lint/definitions/core/date_time.rb +381 -0
- data/lib/ruby-lint/definitions/core/default_record_separator.rb +7 -0
- data/lib/ruby-lint/definitions/core/digest.rb +166 -0
- data/lib/ruby-lint/definitions/core/dir.rb +496 -0
- data/lib/ruby-lint/definitions/core/encoding.rb +2030 -0
- data/lib/ruby-lint/definitions/core/encoding_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/enumerable.rb +352 -0
- data/lib/ruby-lint/definitions/core/enumerator.rb +37 -0
- data/lib/ruby-lint/definitions/core/env.rb +7 -0
- data/lib/ruby-lint/definitions/core/eoferror.rb +8 -0
- data/lib/ruby-lint/definitions/core/erb.rb +304 -0
- data/lib/ruby-lint/definitions/core/errno.rb +3331 -0
- data/lib/ruby-lint/definitions/core/etc.rb +138 -0
- data/lib/ruby-lint/definitions/core/exception.rb +72 -0
- data/lib/ruby-lint/definitions/core/false.rb +7 -0
- data/lib/ruby-lint/definitions/core/false_class.rb +30 -0
- data/lib/ruby-lint/definitions/core/fatal_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/fiber.rb +35 -0
- data/lib/ruby-lint/definitions/core/fiber_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/file.rb +1277 -0
- data/lib/ruby-lint/definitions/core/file_list.rb +727 -0
- data/lib/ruby-lint/definitions/core/file_test.rb +106 -0
- data/lib/ruby-lint/definitions/core/file_utils.rb +1027 -0
- data/lib/ruby-lint/definitions/core/fixnum.rb +156 -0
- data/lib/ruby-lint/definitions/core/float.rb +307 -0
- data/lib/ruby-lint/definitions/core/float_domain_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/gc.rb +57 -0
- data/lib/ruby-lint/definitions/core/gem.rb +3161 -0
- data/lib/ruby-lint/definitions/core/hash.rb +512 -0
- data/lib/ruby-lint/definitions/core/immediate_value.rb +19 -0
- data/lib/ruby-lint/definitions/core/index_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/integer.rb +100 -0
- data/lib/ruby-lint/definitions/core/interrupt.rb +14 -0
- data/lib/ruby-lint/definitions/core/io.rb +928 -0
- data/lib/ruby-lint/definitions/core/ioerror.rb +8 -0
- data/lib/ruby-lint/definitions/core/kernel.rb +504 -0
- data/lib/ruby-lint/definitions/core/key_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/load_error.rb +28 -0
- data/lib/ruby-lint/definitions/core/local_jump_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/main.rb +25 -0
- data/lib/ruby-lint/definitions/core/marshal.rb +466 -0
- data/lib/ruby-lint/definitions/core/match_data.rb +73 -0
- data/lib/ruby-lint/definitions/core/math.rb +205 -0
- data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/method.rb +61 -0
- data/lib/ruby-lint/definitions/core/module.rb +262 -0
- data/lib/ruby-lint/definitions/core/monitor.rb +39 -0
- data/lib/ruby-lint/definitions/core/monitor_mixin.rb +59 -0
- data/lib/ruby-lint/definitions/core/mutex.rb +32 -0
- data/lib/ruby-lint/definitions/core/name_error.rb +16 -0
- data/lib/ruby-lint/definitions/core/nil.rb +7 -0
- data/lib/ruby-lint/definitions/core/nil_class.rb +46 -0
- data/lib/ruby-lint/definitions/core/no_memory_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/no_method_error.rb +18 -0
- data/lib/ruby-lint/definitions/core/not_implemented_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/numeric.rb +123 -0
- data/lib/ruby-lint/definitions/core/object.rb +31 -0
- data/lib/ruby-lint/definitions/core/object_space.rb +41 -0
- data/lib/ruby-lint/definitions/core/open_struct.rb +49 -0
- data/lib/ruby-lint/definitions/core/option_parser.rb +1355 -0
- data/lib/ruby-lint/definitions/core/precision.rb +21 -0
- data/lib/ruby-lint/definitions/core/primitive_failure.rb +8 -0
- data/lib/ruby-lint/definitions/core/proc.rb +109 -0
- data/lib/ruby-lint/definitions/core/process.rb +602 -0
- data/lib/ruby-lint/definitions/core/psych.rb +2231 -0
- data/lib/ruby-lint/definitions/core/queue.rb +44 -0
- data/lib/ruby-lint/definitions/core/rake.rb +4784 -0
- data/lib/ruby-lint/definitions/core/rake_file_utils.rb +203 -0
- data/lib/ruby-lint/definitions/core/rakeversion.rb +7 -0
- data/lib/ruby-lint/definitions/core/random.rb +38 -0
- data/lib/ruby-lint/definitions/core/range.rb +104 -0
- data/lib/ruby-lint/definitions/core/range_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/rational.rb +96 -0
- data/lib/ruby-lint/definitions/core/rb_config.rb +36 -0
- data/lib/ruby-lint/definitions/core/regexp.rb +396 -0
- data/lib/ruby-lint/definitions/core/regexp_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/rubinius.rb +16637 -0
- data/lib/ruby-lint/definitions/core/ruby_copyright.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_description.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_engine.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_lint.rb +93 -0
- data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_platform.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_release_date.rb +7 -0
- data/lib/ruby-lint/definitions/core/ruby_version.rb +7 -0
- data/lib/ruby-lint/definitions/core/runtime_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/scan_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/script_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/security_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/shellwords.rb +37 -0
- data/lib/ruby-lint/definitions/core/signal.rb +37 -0
- data/lib/ruby-lint/definitions/core/signal_exception.rb +19 -0
- data/lib/ruby-lint/definitions/core/singleton.rb +37 -0
- data/lib/ruby-lint/definitions/core/sized_queue.rb +42 -0
- data/lib/ruby-lint/definitions/core/standard_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/stderr.rb +7 -0
- data/lib/ruby-lint/definitions/core/stdin.rb +7 -0
- data/lib/ruby-lint/definitions/core/stdout.rb +7 -0
- data/lib/ruby-lint/definitions/core/stop_iteration.rb +8 -0
- data/lib/ruby-lint/definitions/core/string.rb +713 -0
- data/lib/ruby-lint/definitions/core/string_io.rb +287 -0
- data/lib/ruby-lint/definitions/core/string_scanner.rb +158 -0
- data/lib/ruby-lint/definitions/core/struct.rb +357 -0
- data/lib/ruby-lint/definitions/core/syck.rb +30 -0
- data/lib/ruby-lint/definitions/core/symbol.rb +90 -0
- data/lib/ruby-lint/definitions/core/syntax_error.rb +44 -0
- data/lib/ruby-lint/definitions/core/system_call_error.rb +31 -0
- data/lib/ruby-lint/definitions/core/system_exit.rb +19 -0
- data/lib/ruby-lint/definitions/core/system_stack_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/thread.rb +209 -0
- data/lib/ruby-lint/definitions/core/thread_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/thread_group.rb +22 -0
- data/lib/ruby-lint/definitions/core/time.rb +233 -0
- data/lib/ruby-lint/definitions/core/toplevel_binding.rb +7 -0
- data/lib/ruby-lint/definitions/core/true.rb +7 -0
- data/lib/ruby-lint/definitions/core/true_class.rb +30 -0
- data/lib/ruby-lint/definitions/core/type_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/unbound_method.rb +51 -0
- data/lib/ruby-lint/definitions/core/unmarshalable.rb +13 -0
- data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +8 -0
- data/lib/ruby-lint/definitions/core/weak_ref.rb +42 -0
- data/lib/ruby-lint/definitions/core/zero_division_error.rb +8 -0
- data/lib/ruby-lint/definitions_builder.rb +692 -0
- data/lib/ruby-lint/extensions/string.rb +15 -0
- data/lib/ruby-lint/helper/constant_paths.rb +41 -0
- data/lib/ruby-lint/helper/conversion.rb +33 -0
- data/lib/ruby-lint/helper/current_scope.rb +98 -0
- data/lib/ruby-lint/helper/methods.rb +91 -0
- data/lib/ruby-lint/inspector.rb +191 -0
- data/lib/ruby-lint/iterator.rb +187 -127
- data/lib/ruby-lint/node.rb +107 -0
- data/lib/ruby-lint/parser.rb +510 -1137
- data/lib/ruby-lint/parser_error.rb +15 -27
- data/lib/ruby-lint/presenter/json.rb +19 -0
- data/lib/ruby-lint/presenter/text.rb +37 -0
- data/lib/ruby-lint/report.rb +95 -53
- data/lib/ruby-lint/report/entry.rb +71 -0
- data/lib/ruby-lint/template/definition.erb +24 -0
- data/lib/ruby-lint/template/scope.rb +25 -0
- data/lib/ruby-lint/variable_predicates.rb +109 -0
- data/lib/ruby-lint/version.rb +1 -1
- data/ruby-lint.gemspec +19 -8
- data/spec/helper.rb +10 -2
- data/spec/ruby-lint/analyze/argument_amount.rb +91 -0
- data/spec/ruby-lint/analyze/shadowing_variables.rb +69 -14
- data/spec/ruby-lint/analyze/undefined_methods.rb +174 -0
- data/spec/ruby-lint/analyze/undefined_variables.rb +70 -179
- data/spec/ruby-lint/analyze/unused_variables.rb +63 -183
- data/spec/ruby-lint/configuration.rb +15 -0
- data/spec/ruby-lint/constant_loader.rb +32 -0
- data/spec/ruby-lint/definition/dsl.rb +142 -0
- data/spec/ruby-lint/definition/method_calls.rb +26 -0
- data/spec/ruby-lint/definition/ruby_method.rb +175 -0
- data/spec/ruby-lint/definition/ruby_object.rb +228 -0
- data/spec/ruby-lint/definitions_builder/assignments/arrays.rb +71 -0
- data/spec/ruby-lint/definitions_builder/assignments/hashes.rb +65 -0
- data/spec/ruby-lint/definitions_builder/assignments/objects.rb +23 -0
- data/spec/ruby-lint/definitions_builder/assignments/optional.rb +22 -0
- data/spec/ruby-lint/definitions_builder/assignments/return_values.rb +78 -0
- data/spec/ruby-lint/definitions_builder/assignments/variables.rb +71 -0
- data/spec/ruby-lint/definitions_builder/associate_nodes.rb +17 -0
- data/spec/ruby-lint/definitions_builder/blocks.rb +40 -0
- data/spec/ruby-lint/definitions_builder/classes.rb +230 -0
- data/spec/ruby-lint/definitions_builder/for.rb +16 -0
- data/spec/ruby-lint/definitions_builder/methods.rb +147 -0
- data/spec/ruby-lint/definitions_builder/modules.rb +175 -0
- data/spec/ruby-lint/definitions_builder/reference_amount.rb +31 -0
- data/spec/ruby-lint/definitions_builder/unused.rb +15 -0
- data/spec/ruby-lint/extensions/string.rb +7 -0
- data/spec/ruby-lint/iterator.rb +42 -417
- data/spec/ruby-lint/node.rb +38 -0
- data/spec/ruby-lint/parser/assignments.rb +225 -0
- data/spec/ruby-lint/parser/classes.rb +80 -122
- data/spec/ruby-lint/parser/errors.rb +7 -14
- data/spec/ruby-lint/parser/metadata.rb +17 -0
- data/spec/ruby-lint/parser/method_definitions.rb +111 -0
- data/spec/ruby-lint/parser/methods.rb +184 -216
- data/spec/ruby-lint/parser/modules.rb +54 -33
- data/spec/ruby-lint/parser/operators.rb +30 -65
- data/spec/ruby-lint/parser/statements/begin.rb +55 -0
- data/spec/ruby-lint/parser/statements/case.rb +34 -0
- data/spec/ruby-lint/parser/statements/defined.rb +11 -0
- data/spec/ruby-lint/parser/statements/for.rb +34 -0
- data/spec/ruby-lint/parser/statements/if.rb +46 -0
- data/spec/ruby-lint/parser/statements/return.rb +14 -0
- data/spec/ruby-lint/parser/statements/super.rb +49 -0
- data/spec/ruby-lint/parser/statements/unless.rb +42 -0
- data/spec/ruby-lint/parser/statements/until.rb +25 -0
- data/spec/ruby-lint/parser/statements/while.rb +25 -0
- data/spec/ruby-lint/parser/statements/yield.rb +18 -0
- data/spec/ruby-lint/parser/types/arrays.rb +47 -0
- data/spec/ruby-lint/parser/types/booleans.rb +11 -0
- data/spec/ruby-lint/parser/types/constants.rb +32 -0
- data/spec/ruby-lint/parser/types/hashes.rb +55 -0
- data/spec/ruby-lint/parser/types/nil.rb +7 -0
- data/spec/ruby-lint/parser/types/numbers.rb +11 -0
- data/spec/ruby-lint/parser/types/procs.rb +11 -0
- data/spec/ruby-lint/parser/types/ranges.rb +11 -0
- data/spec/ruby-lint/parser/types/regexp.rb +27 -0
- data/spec/ruby-lint/parser/types/strings.rb +44 -0
- data/spec/ruby-lint/parser/types/symbols.rb +15 -0
- data/spec/ruby-lint/presenter/json.rb +31 -0
- data/spec/ruby-lint/presenter/text.rb +22 -0
- data/spec/ruby-lint/report.rb +45 -15
- data/spec/ruby-lint/report/entry.rb +24 -0
- data/spec/support/bacon.rb +33 -0
- data/spec/support/building.rb +43 -0
- data/spec/support/definitions.rb +23 -0
- data/spec/support/parsing.rb +23 -0
- data/spec/support/simplecov.rb +16 -0
- data/task/build.rake +9 -0
- data/task/checksum.rake +13 -0
- data/task/coverage.rake +6 -0
- data/task/doc.rake +5 -0
- data/task/generate.rake +34 -0
- data/task/graphviz.rake +12 -0
- data/task/stdlib.rake +2 -9
- data/task/tag.rake +6 -0
- metadata +337 -68
- metadata.gz.asc +17 -0
- data/.rbenv-version +0 -1
- data/lib/ruby-lint/analyze/coding_style.rb +0 -407
- data/lib/ruby-lint/analyze/definitions.rb +0 -244
- data/lib/ruby-lint/analyze/method_validation.rb +0 -104
- data/lib/ruby-lint/callback.rb +0 -67
- data/lib/ruby-lint/constant_importer.rb +0 -112
- data/lib/ruby-lint/definition.rb +0 -230
- data/lib/ruby-lint/formatter/text.rb +0 -54
- data/lib/ruby-lint/helper/definition_resolver.rb +0 -143
- data/lib/ruby-lint/helper/scoping.rb +0 -138
- data/lib/ruby-lint/options.rb +0 -58
- data/lib/ruby-lint/token/assignment_token.rb +0 -35
- data/lib/ruby-lint/token/begin_rescue_token.rb +0 -57
- data/lib/ruby-lint/token/block_token.rb +0 -26
- data/lib/ruby-lint/token/case_token.rb +0 -44
- data/lib/ruby-lint/token/class_token.rb +0 -24
- data/lib/ruby-lint/token/keyword_token.rb +0 -43
- data/lib/ruby-lint/token/method_definition_token.rb +0 -64
- data/lib/ruby-lint/token/method_token.rb +0 -56
- data/lib/ruby-lint/token/parameters_token.rb +0 -99
- data/lib/ruby-lint/token/regexp_token.rb +0 -15
- data/lib/ruby-lint/token/statement_token.rb +0 -69
- data/lib/ruby-lint/token/token.rb +0 -176
- data/lib/ruby-lint/token/variable_token.rb +0 -18
- data/spec/benchmarks/memory.rb +0 -52
- data/spec/benchmarks/parse_parser.rb +0 -16
- data/spec/fixtures/stdlib/un.rb +0 -348
- data/spec/ruby-lint/analyze/coding_style.rb +0 -224
- data/spec/ruby-lint/analyze/complex/un.rb +0 -29
- data/spec/ruby-lint/analyze/definitions/classes.rb +0 -114
- data/spec/ruby-lint/analyze/definitions/methods.rb +0 -91
- data/spec/ruby-lint/analyze/definitions/modules.rb +0 -207
- data/spec/ruby-lint/analyze/definitions/variables.rb +0 -103
- data/spec/ruby-lint/analyze/method_validation.rb +0 -177
- data/spec/ruby-lint/callback.rb +0 -28
- data/spec/ruby-lint/constant_importer.rb +0 -27
- data/spec/ruby-lint/definition.rb +0 -96
- data/spec/ruby-lint/formatter/text.rb +0 -21
- data/spec/ruby-lint/parser/arrays.rb +0 -147
- data/spec/ruby-lint/parser/expander_assignments.rb +0 -183
- data/spec/ruby-lint/parser/hashes.rb +0 -136
- data/spec/ruby-lint/parser/keywords.rb +0 -89
- data/spec/ruby-lint/parser/objects.rb +0 -39
- data/spec/ruby-lint/parser/procs.rb +0 -113
- data/spec/ruby-lint/parser/ranges.rb +0 -49
- data/spec/ruby-lint/parser/regexp.rb +0 -31
- data/spec/ruby-lint/parser/scalars.rb +0 -93
- data/spec/ruby-lint/parser/statements.rb +0 -591
- data/spec/ruby-lint/parser/variables.rb +0 -230
@@ -0,0 +1,92 @@
|
|
1
|
+
module RubyLint
|
2
|
+
##
|
3
|
+
# The ConstantLoader class tries to pre-load various constants in a given
|
4
|
+
# file before the definitions are being built and analysis is performed.
|
5
|
+
#
|
6
|
+
# Note that this pre-loader is rather basic and as such there are chances you
|
7
|
+
# still have to manually require definitions to ensure that they are being
|
8
|
+
# used.
|
9
|
+
#
|
10
|
+
# @!attribute [r] loaded
|
11
|
+
# @return [Hash] Hash containing the loaded constants.
|
12
|
+
#
|
13
|
+
class ConstantLoader < Iterator
|
14
|
+
attr_reader :loaded
|
15
|
+
|
16
|
+
##
|
17
|
+
# List of directories to search for definition files.
|
18
|
+
#
|
19
|
+
# @return [Array]
|
20
|
+
#
|
21
|
+
LOAD_PATH = [
|
22
|
+
File.expand_path('../definitions/core', __FILE__)
|
23
|
+
]
|
24
|
+
|
25
|
+
##
|
26
|
+
# @see RubyLint::Iterator#initialize
|
27
|
+
#
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
|
31
|
+
@loaded = {}
|
32
|
+
@in_constant_path = false
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# @param [RubyLint::Node] node
|
37
|
+
#
|
38
|
+
def on_constant_path(node)
|
39
|
+
@in_constant_path = true
|
40
|
+
|
41
|
+
load(node.children.first.name)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @param [RubyLint::Node] node
|
46
|
+
#
|
47
|
+
def after_constant_path(node)
|
48
|
+
@in_constant_path = false
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# @param [RubyLint::Node] node
|
53
|
+
#
|
54
|
+
def on_constant(node)
|
55
|
+
return if @in_constant_path
|
56
|
+
|
57
|
+
load(node.name)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Checks if the given constant is already loaded or not.
|
62
|
+
#
|
63
|
+
# @param [String] constant
|
64
|
+
# @return [TrueClass|FalseClass]
|
65
|
+
#
|
66
|
+
def loaded?(constant)
|
67
|
+
return loaded.key?(constant)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Tries to load the definitions for the given constant.
|
72
|
+
#
|
73
|
+
# @param [String] constant
|
74
|
+
#
|
75
|
+
def load(constant)
|
76
|
+
return if loaded?(constant)
|
77
|
+
|
78
|
+
filename = constant.snake_case + '.rb'
|
79
|
+
|
80
|
+
LOAD_PATH.each do |path|
|
81
|
+
path = File.join(path, filename)
|
82
|
+
|
83
|
+
if File.file?(path)
|
84
|
+
require(path)
|
85
|
+
loaded[constant] = true
|
86
|
+
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end # ConstantLoader
|
92
|
+
end # RubyLint
|
@@ -0,0 +1,248 @@
|
|
1
|
+
module RubyLint
|
2
|
+
module Definition
|
3
|
+
##
|
4
|
+
# The RubyMethod definition class is a definition class used for storing
|
5
|
+
# information about Ruby methods (both class and instance methods).
|
6
|
+
#
|
7
|
+
# @see RubyLint::Definition::RubyObject
|
8
|
+
#
|
9
|
+
# @!attribute [r] visibility
|
10
|
+
# @return [Symbol] The method visibility such as `:public`.
|
11
|
+
#
|
12
|
+
# @!attribute [r] arguments
|
13
|
+
# @return [Array] The required/specified arguments of a method definition
|
14
|
+
# or method call.
|
15
|
+
#
|
16
|
+
# @!attribute [r] optional_arguments
|
17
|
+
# @return [Array] Array containing the optional arguments of a method
|
18
|
+
# definition.
|
19
|
+
#
|
20
|
+
# @!attribute [r] rest_argument
|
21
|
+
# @return [RubyLint::Definition::RubyObject] The rest argument of a
|
22
|
+
# method definition.
|
23
|
+
#
|
24
|
+
# @!attribute [r] more_arguments
|
25
|
+
# @return [Array] A set of "more" arguments of the method definition.
|
26
|
+
#
|
27
|
+
# @!attribute [r] block_argument
|
28
|
+
# @return [RubyLint::Definition::RubyObject] The block argument of a
|
29
|
+
# method definition.
|
30
|
+
#
|
31
|
+
# @!attribute [r] method_type
|
32
|
+
# @return [Symbol] The type of method definition, set to `:method` for
|
33
|
+
# class methods and `:instance_method` for instance methods.
|
34
|
+
#
|
35
|
+
# @!attribute [r] return_value
|
36
|
+
# @return [Mixed] The value that is returned by the method.
|
37
|
+
#
|
38
|
+
class RubyMethod < RubyObject
|
39
|
+
##
|
40
|
+
# Hash that contains the node types and attribute names to store the
|
41
|
+
# arguments in.
|
42
|
+
#
|
43
|
+
# @return [Hash]
|
44
|
+
#
|
45
|
+
ARGUMENT_TYPE_MAPPING = {
|
46
|
+
:argument => :arguments,
|
47
|
+
:optional_argument => :optional_arguments,
|
48
|
+
:rest_argument => :rest_argument,
|
49
|
+
:more_argument => :more_arguments,
|
50
|
+
:block_argument => :block_argument
|
51
|
+
}
|
52
|
+
|
53
|
+
attr_reader :block_argument,
|
54
|
+
:arguments,
|
55
|
+
:method_type,
|
56
|
+
:more_arguments,
|
57
|
+
:optional_arguments,
|
58
|
+
:rest_argument,
|
59
|
+
:return_value,
|
60
|
+
:visibility
|
61
|
+
|
62
|
+
##
|
63
|
+
# @see RubyLint::Definition::RubyObject#new_from_node
|
64
|
+
#
|
65
|
+
def self.new_from_node(node, options = {})
|
66
|
+
options = default_method_options.merge(options)
|
67
|
+
options = options.merge(gather_arguments(node))
|
68
|
+
receiver = node.receiver
|
69
|
+
|
70
|
+
options[:method_type] ||= node.method_type
|
71
|
+
|
72
|
+
if receiver
|
73
|
+
options[:receiver] = RubyObject.new_from_node(receiver)
|
74
|
+
options[:method_type] = :method
|
75
|
+
end
|
76
|
+
|
77
|
+
return super(node, options)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Returns a Hash containing all the arguments grouped together based on
|
82
|
+
# their types.
|
83
|
+
#
|
84
|
+
# @param [RubyLint::Node] node
|
85
|
+
# @return [Hash]
|
86
|
+
#
|
87
|
+
def self.gather_arguments(node)
|
88
|
+
arguments = default_arguments
|
89
|
+
|
90
|
+
ARGUMENT_TYPE_MAPPING.each do |from, to|
|
91
|
+
args = node.gather_arguments(from)
|
92
|
+
args = args.map { |n| RubyObject.new_from_node(n, :value => n.value) }
|
93
|
+
|
94
|
+
arguments[to] = arguments[to].is_a?(Array) ? args : args[0]
|
95
|
+
end
|
96
|
+
|
97
|
+
return arguments
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Returns the default Hash for a set of method arguments.
|
102
|
+
#
|
103
|
+
# @return [Hash]
|
104
|
+
#
|
105
|
+
def self.default_arguments
|
106
|
+
return {
|
107
|
+
:arguments => [],
|
108
|
+
:optional_arguments => [],
|
109
|
+
:rest_argument => nil,
|
110
|
+
:more_arguments => [],
|
111
|
+
:block_argument => nil
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Returns a Hash containing the default options for this class. The name
|
117
|
+
# is different than {RubyLint::Definition::RubyObject#default_options} to
|
118
|
+
# prevent any naming issues.
|
119
|
+
#
|
120
|
+
# @return [Hash]
|
121
|
+
#
|
122
|
+
def self.default_method_options
|
123
|
+
return {:method_type => :instance_method}
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# @see RubyLint::Definition::RubyObject#initialize
|
128
|
+
#
|
129
|
+
def initialize(*args)
|
130
|
+
@arguments = []
|
131
|
+
@optional_arguments = []
|
132
|
+
@more_arguments = []
|
133
|
+
|
134
|
+
super
|
135
|
+
|
136
|
+
define_arguments unless method?
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Sets the return value of this method. If a block is given it will be
|
141
|
+
# used as the return value. The block is *not* evaluated until it's
|
142
|
+
# called.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# string.define_instance_method(:gsub) do |method|
|
146
|
+
# method.returns('...')
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# @param [Mixed] value
|
150
|
+
#
|
151
|
+
def returns(value = nil, &block)
|
152
|
+
@return_value = block_given? ? block : value
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Defines a required argument for the method.
|
157
|
+
#
|
158
|
+
# @example
|
159
|
+
# method.define_argument('number')
|
160
|
+
#
|
161
|
+
# @param [String] name The name of the argument.
|
162
|
+
#
|
163
|
+
def define_argument(name)
|
164
|
+
@arguments << create_variable(name)
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Defines a optional argument for the method.
|
169
|
+
#
|
170
|
+
# @see RubyLint::Definition::RubyObject#define_argument
|
171
|
+
#
|
172
|
+
def define_optional_argument(name)
|
173
|
+
@optional_arguments << create_variable(name)
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Defines a rest argument for the method.
|
178
|
+
#
|
179
|
+
# @see RubyLint::Definition::RubyObject#define_argument
|
180
|
+
#
|
181
|
+
def define_rest_argument(name)
|
182
|
+
@rest_argument = create_variable(name)
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Defines a more argument for the method.
|
187
|
+
#
|
188
|
+
# @see RubyLint::Definition::RubyObject#define_argument
|
189
|
+
#
|
190
|
+
def define_more_argument(name)
|
191
|
+
@more_arguments << create_variable(name)
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# Defines a block argument for the method.
|
196
|
+
#
|
197
|
+
# @see RubyLint::Definition::RubyObject#define_argument
|
198
|
+
#
|
199
|
+
def define_block_argument(name)
|
200
|
+
@block_argument = create_variable(name)
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
##
|
206
|
+
# Adds all the arguments of this method to the definitions list.
|
207
|
+
#
|
208
|
+
def define_arguments
|
209
|
+
all_arguments.each do |params|
|
210
|
+
next unless params
|
211
|
+
|
212
|
+
params.each do |param|
|
213
|
+
add(param.type, param.name, param) if param
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Returns an Array containing all the method arguments. Each arguments
|
220
|
+
# set (even single ones such as the more argument) is returned as an
|
221
|
+
# Array making it easier to iterate over the collection.
|
222
|
+
#
|
223
|
+
# @return [Array]
|
224
|
+
#
|
225
|
+
def all_arguments
|
226
|
+
return [
|
227
|
+
arguments,
|
228
|
+
optional_arguments,
|
229
|
+
[rest_argument],
|
230
|
+
more_arguments,
|
231
|
+
[block_argument]
|
232
|
+
]
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# @param [String] name
|
237
|
+
# @return [RubyLint::Definition::RubyObject]
|
238
|
+
#
|
239
|
+
def create_variable(name)
|
240
|
+
variable = RubyObject.new(:type => :local_variable, :name => name)
|
241
|
+
|
242
|
+
add(variable.type, variable.name, variable)
|
243
|
+
|
244
|
+
return variable
|
245
|
+
end
|
246
|
+
end # RubyMethod
|
247
|
+
end # Definition
|
248
|
+
end # RubyLint
|
@@ -0,0 +1,757 @@
|
|
1
|
+
module RubyLint
|
2
|
+
module Definition
|
3
|
+
##
|
4
|
+
# The RubyObject class is the base definition class of ruby-lint. These so
|
5
|
+
# called definition classes are used for storing information about Ruby
|
6
|
+
# classes and instances. At their most basic form they are a mix between
|
7
|
+
# {RubyLint::Node} and a lookup table.
|
8
|
+
#
|
9
|
+
# ruby-lint currently provides the following two definition classes:
|
10
|
+
#
|
11
|
+
# * {RubyLint::Definition::RubyObject}: the base definition class, used for
|
12
|
+
# most Ruby types and values.
|
13
|
+
# * {RubyLint::Definition::RubyMethod} definition class that is used for
|
14
|
+
# methods exclusively.
|
15
|
+
#
|
16
|
+
# Using the RubyObject class one could create a definition for the String
|
17
|
+
# class as following:
|
18
|
+
#
|
19
|
+
# string = RubyObject.new(:name => 'String', :type => :constant)
|
20
|
+
# newline = RubyObject.new(
|
21
|
+
# :name => 'NEWLINE',
|
22
|
+
# :type => :constant,
|
23
|
+
# :value => "\n"
|
24
|
+
# )
|
25
|
+
#
|
26
|
+
# string.add(:constant, newline.name, newline)
|
27
|
+
#
|
28
|
+
# For more information see the documentation of the corresponding methods.
|
29
|
+
#
|
30
|
+
# @!attribute [r] name
|
31
|
+
# @return [String] The name of the object.
|
32
|
+
#
|
33
|
+
# @!attribute [rw] value
|
34
|
+
# @return [Mixed] The value of the object.
|
35
|
+
#
|
36
|
+
# @!attribute [r] type
|
37
|
+
# @return [Symbol] The type of object, e.g. `:constant`.
|
38
|
+
#
|
39
|
+
# @!attribute [r] ignore
|
40
|
+
# @return [TrueClass|FalseClass] When set to `true` the definition should
|
41
|
+
# be ignored by any analysis related code. This is mostly used when no
|
42
|
+
# meaningful data could be assigned (e.g. block arguments).
|
43
|
+
#
|
44
|
+
# @!attribute [r] definitions
|
45
|
+
# @return [Hash] Hash containing all child the definitions.
|
46
|
+
#
|
47
|
+
# @!attribute [rw] parents
|
48
|
+
# @return [Array] Array containing the parent definitions.
|
49
|
+
#
|
50
|
+
# @!attribute [rw] receiver
|
51
|
+
# @return [RubyLint::Definition::RubyObject] The receiver on which the
|
52
|
+
# object was defined/called.
|
53
|
+
#
|
54
|
+
# @!attribute [rw] reference_amount
|
55
|
+
# @return [Numeric] The amount of times an object was referenced.
|
56
|
+
# Currently this is only used for variables.
|
57
|
+
#
|
58
|
+
# @!attribute [rw] instance_type
|
59
|
+
# @return [Symbol] Indicates if the object represents a class or an
|
60
|
+
# instance.
|
61
|
+
#
|
62
|
+
# @!attribute [r] update_parents
|
63
|
+
# @return [Array] A list of data types to also add to the parent
|
64
|
+
# definitions when adding an object to the current one.
|
65
|
+
#
|
66
|
+
class RubyObject
|
67
|
+
include VariablePredicates
|
68
|
+
|
69
|
+
##
|
70
|
+
# Array containing items that should be looked up in the parent
|
71
|
+
# definition if they're not found in the current one.
|
72
|
+
#
|
73
|
+
# @return [Array]
|
74
|
+
#
|
75
|
+
LOOKUP_PARENT = [
|
76
|
+
:class_variable,
|
77
|
+
:constant,
|
78
|
+
:global_variable,
|
79
|
+
:instance_method,
|
80
|
+
:instance_variable,
|
81
|
+
:keyword,
|
82
|
+
:method
|
83
|
+
]
|
84
|
+
|
85
|
+
##
|
86
|
+
# String used to separate segments in a constant path.
|
87
|
+
#
|
88
|
+
# @return [String]
|
89
|
+
#
|
90
|
+
PATH_SEPARATOR = '::'
|
91
|
+
|
92
|
+
attr_reader :update_parents,
|
93
|
+
:column,
|
94
|
+
:definitions,
|
95
|
+
:ignore,
|
96
|
+
:name,
|
97
|
+
:type,
|
98
|
+
:value
|
99
|
+
|
100
|
+
attr_accessor :instance_type,
|
101
|
+
:parents,
|
102
|
+
:receiver,
|
103
|
+
:reference_amount
|
104
|
+
|
105
|
+
##
|
106
|
+
# Creates a new RubyObject instance based on an instance of
|
107
|
+
# {RubyLint::Node}. This method is primarily used in
|
108
|
+
# {RubyLint::DefinitionsBuilder}, in most cases third-party code should
|
109
|
+
# not have a need for this method.
|
110
|
+
#
|
111
|
+
# @param [RubyLint::Node] node
|
112
|
+
# @return [RubyLint::Definition::RubyObject]
|
113
|
+
#
|
114
|
+
def self.new_from_node(node, options = {})
|
115
|
+
path_segments = []
|
116
|
+
|
117
|
+
if node.constant_path?
|
118
|
+
path_segments = node.children[0..-2].reverse
|
119
|
+
node = node.children[-1]
|
120
|
+
end
|
121
|
+
|
122
|
+
options[:name] ||= node.name
|
123
|
+
options[:type] ||= node.type
|
124
|
+
|
125
|
+
# Checking to see if :value evaluates to `true` would mean you could
|
126
|
+
# never manually assign a nil value.
|
127
|
+
unless options.key?(:value)
|
128
|
+
options[:value] = node.value
|
129
|
+
end
|
130
|
+
|
131
|
+
if options[:value]
|
132
|
+
options[:value] = create_value_definitions(options[:value])
|
133
|
+
end
|
134
|
+
|
135
|
+
object = new(options)
|
136
|
+
|
137
|
+
# Assign the receivers of this object.
|
138
|
+
#
|
139
|
+
# TODO: this approach doesn't take existing definitions into account,
|
140
|
+
# instead it will always create a new one for each segment.
|
141
|
+
if !path_segments.empty? and !options[:receiver]
|
142
|
+
path_segments.inject(object) do |source, segment|
|
143
|
+
source.receiver = new_from_node(segment)
|
144
|
+
source.receiver
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
return object
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Converts either a single {RubyLint::Node} instance or a collection of
|
153
|
+
# instances into {RubyObject} instances.
|
154
|
+
#
|
155
|
+
# @param [RubyLint::Node|Array<RubyLint::Node>] value
|
156
|
+
# @return [RubyLint::Node|Array<RubyLint::Node>]
|
157
|
+
#
|
158
|
+
def self.create_value_definitions(value)
|
159
|
+
if value.is_a?(Array)
|
160
|
+
value = value.map { |v| create_value_definitions(v) }
|
161
|
+
elsif value.is_a?(Node)
|
162
|
+
value = RubyObject.new_from_node(value)
|
163
|
+
end
|
164
|
+
|
165
|
+
return value
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# @example
|
170
|
+
# string = RubyObject.new(:name => 'String', :type => :constant)
|
171
|
+
#
|
172
|
+
# @param [Hash] options Hash containing additional options such as the
|
173
|
+
# parent definitions. For a list of available options see the
|
174
|
+
# corresponding getter/setter methods of this class.
|
175
|
+
#
|
176
|
+
# @yieldparam [RubyLint::Definition::RubyObject]
|
177
|
+
#
|
178
|
+
def initialize(options = {})
|
179
|
+
options = default_options.merge(options)
|
180
|
+
|
181
|
+
options.each do |key, value|
|
182
|
+
instance_variable_set("@#{key}", value)
|
183
|
+
end
|
184
|
+
|
185
|
+
clear!
|
186
|
+
|
187
|
+
yield self if block_given?
|
188
|
+
end
|
189
|
+
|
190
|
+
##
|
191
|
+
# Sets the value of the definition. If a {RubyLint::Node} instance is
|
192
|
+
# specified it will be converted to a definition instance.
|
193
|
+
#
|
194
|
+
# @param [RubyLint::Definition::RubyObject|RubyLint::Node] value
|
195
|
+
#
|
196
|
+
def value=(value)
|
197
|
+
@value = value.is_a?(Node) ? RubyObject.new_from_node(value) : value
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# Adds a new definition to the definitions list.
|
202
|
+
#
|
203
|
+
# @example
|
204
|
+
# string = RubyObject.new(:name => 'String', :type => :constant)
|
205
|
+
# newline = RubyObject.new(
|
206
|
+
# :name => 'NEWLINE',
|
207
|
+
# :type => :constant,
|
208
|
+
# :value => "\n"
|
209
|
+
# )
|
210
|
+
#
|
211
|
+
# string.add(newline.type, newline.name, newline)
|
212
|
+
#
|
213
|
+
# @param [#to_sym] type The type of definition to add.
|
214
|
+
# @param [String] name The name of the definition.
|
215
|
+
# @param [RubyLint::Definition::RubyObject] value
|
216
|
+
#
|
217
|
+
# @raise [TypeError] Raised when a value that is not a RubyObject
|
218
|
+
# instance (or a subclass of this class) is given.
|
219
|
+
#
|
220
|
+
# @raise [ArgumentError] Raised when the specified type was invalid.
|
221
|
+
#
|
222
|
+
def add(type, name, value)
|
223
|
+
type = prepare_type(type)
|
224
|
+
|
225
|
+
unless value.is_a?(RubyObject)
|
226
|
+
raise TypeError, "Expected RubyObject but got #{value.class}"
|
227
|
+
end
|
228
|
+
|
229
|
+
unless definitions.key?(type)
|
230
|
+
raise ArgumentError, ":#{type} is not a valid type of data to add"
|
231
|
+
end
|
232
|
+
|
233
|
+
definitions[type][name] = value
|
234
|
+
|
235
|
+
if update_parents.include?(type)
|
236
|
+
update_parent_definitions(type, name, value)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
##
|
241
|
+
# Looks up a definition by the given type and name. If no data was found
|
242
|
+
# this method will try to look it up in any parent definitions.
|
243
|
+
#
|
244
|
+
# If no definition was found `nil` will be returned.
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# string = RubyObject.new(:name => 'String', :type => :constant)
|
248
|
+
# newline = RubyObject.new(
|
249
|
+
# :name => 'NEWLINE',
|
250
|
+
# :type => :constant,
|
251
|
+
# :value => "\n"
|
252
|
+
# )
|
253
|
+
#
|
254
|
+
# string.add(newline.type, newline.name, newline)
|
255
|
+
#
|
256
|
+
# string.lookup(:constant, 'NEWLINE') # => #<RubyLint::Definition...>
|
257
|
+
#
|
258
|
+
# @param [#to_sym] type
|
259
|
+
# @param [String] name
|
260
|
+
# @return [RubyLint::Definition::RubyObject|NilClass]
|
261
|
+
#
|
262
|
+
def lookup(type, name)
|
263
|
+
type, name = prepare_lookup(type, name)
|
264
|
+
found = nil
|
265
|
+
|
266
|
+
if defines?(type, name)
|
267
|
+
found = definitions[type][name]
|
268
|
+
|
269
|
+
# Look up the definition in the parent scope(s) (if any are set).
|
270
|
+
elsif lookup_parent?(type)
|
271
|
+
parents.each do |parent|
|
272
|
+
parent_definition = parent.lookup(type, name)
|
273
|
+
|
274
|
+
if parent_definition
|
275
|
+
found = parent_definition
|
276
|
+
break
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
return found
|
282
|
+
end
|
283
|
+
|
284
|
+
##
|
285
|
+
# Returns the definition for the given constant path. If one of the
|
286
|
+
# segments does not exist an error is raised instead.
|
287
|
+
#
|
288
|
+
# @example
|
289
|
+
# example.lookup_constant_path('A::B') # => #<RubyLint::Definition...>
|
290
|
+
#
|
291
|
+
# @param [String|Array<String>] path
|
292
|
+
# @return [RubyLint::Definition::RubyObject]
|
293
|
+
# @raise [ArgumentError] Raised when an invalid constant path is
|
294
|
+
# specified.
|
295
|
+
#
|
296
|
+
def lookup_constant_path(path)
|
297
|
+
constant = self
|
298
|
+
path = path.split(PATH_SEPARATOR) if path.is_a?(String)
|
299
|
+
|
300
|
+
path.each do |segment|
|
301
|
+
found = constant.lookup(:constant, segment)
|
302
|
+
|
303
|
+
if found
|
304
|
+
constant = found
|
305
|
+
else
|
306
|
+
name = path.join(PATH_SEPARATOR)
|
307
|
+
|
308
|
+
raise ArgumentError, "Invalid constant path: #{name}"
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
return constant
|
313
|
+
end
|
314
|
+
|
315
|
+
##
|
316
|
+
# Mimics a method call based on the given method name and the instance
|
317
|
+
# type of the current definition.
|
318
|
+
#
|
319
|
+
# If the return value of a method definition is set to a Proc (or any
|
320
|
+
# other object that responds to `:call`) it will be called and passed the
|
321
|
+
# current instance as an argument.
|
322
|
+
#
|
323
|
+
# @todo Support for method arguments, if needed.
|
324
|
+
# @param [String] name The name of the method to call.
|
325
|
+
# @return [Mixed]
|
326
|
+
#
|
327
|
+
def call(name)
|
328
|
+
method = lookup(method_call_type, name)
|
329
|
+
return_value = nil
|
330
|
+
|
331
|
+
if method
|
332
|
+
return_value = method.return_value
|
333
|
+
|
334
|
+
if return_value.respond_to?(:call)
|
335
|
+
return_value = return_value.call(self)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
return return_value
|
340
|
+
end
|
341
|
+
|
342
|
+
##
|
343
|
+
# Returns `true` if the current definition list or one of the parents has
|
344
|
+
# the specified definition.
|
345
|
+
#
|
346
|
+
# @example
|
347
|
+
# string.has_definition?(:instance_method, 'downcase') # => true
|
348
|
+
#
|
349
|
+
# @param [#to_sym] type
|
350
|
+
# @param [String] name
|
351
|
+
# @return [TrueClass|FalseClass]
|
352
|
+
#
|
353
|
+
def has_definition?(type, name)
|
354
|
+
type, name = prepare_lookup(type, name)
|
355
|
+
|
356
|
+
if definitions[type] and definitions[type][name]
|
357
|
+
return true
|
358
|
+
|
359
|
+
elsif lookup_parent?(type)
|
360
|
+
parents.each do |parent|
|
361
|
+
return true if parent.has_definition?(type, name)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
return false
|
366
|
+
end
|
367
|
+
|
368
|
+
##
|
369
|
+
# Determines the call types for methods called on the current definition.
|
370
|
+
#
|
371
|
+
# @return [Symbol]
|
372
|
+
#
|
373
|
+
def method_call_type
|
374
|
+
return class? ? :method : :instance_method
|
375
|
+
end
|
376
|
+
|
377
|
+
##
|
378
|
+
# @return [TrueClass|FalseClass]
|
379
|
+
#
|
380
|
+
def class?
|
381
|
+
return instance_type == :class
|
382
|
+
end
|
383
|
+
|
384
|
+
##
|
385
|
+
# @return [TrueClass|FalseClass]
|
386
|
+
#
|
387
|
+
def instance?
|
388
|
+
return instance_type == :instance
|
389
|
+
end
|
390
|
+
|
391
|
+
##
|
392
|
+
# Updates the definition object so that it represents an instance of a
|
393
|
+
# Ruby value.
|
394
|
+
#
|
395
|
+
def instance!
|
396
|
+
@instance_type = :instance
|
397
|
+
end
|
398
|
+
|
399
|
+
##
|
400
|
+
# Checks if the specified definition is defined in the current object,
|
401
|
+
# ignoring data in any parent definitions.
|
402
|
+
#
|
403
|
+
# @see RubyLint::Definition::RubyObject#has_definition?
|
404
|
+
# @return [TrueClass|FalseClass]
|
405
|
+
#
|
406
|
+
def defines?(type, name)
|
407
|
+
type, name = prepare_lookup(type, name)
|
408
|
+
|
409
|
+
return definitions[type] && definitions[type][name]
|
410
|
+
end
|
411
|
+
|
412
|
+
##
|
413
|
+
# Returns a list of all the definitions for the specific type. This list
|
414
|
+
# excludes anything defined in parent definitions.
|
415
|
+
#
|
416
|
+
# @example
|
417
|
+
# string.list(:instance_method) # => [..., ..., ...]
|
418
|
+
#
|
419
|
+
# @param [#to_sym] type
|
420
|
+
# @return [Array]
|
421
|
+
#
|
422
|
+
def list(type)
|
423
|
+
return definitions[prepare_type(type)].values
|
424
|
+
end
|
425
|
+
|
426
|
+
##
|
427
|
+
# Returns the length of an attribute or 0.
|
428
|
+
#
|
429
|
+
# @param [#to_sym] attribute
|
430
|
+
# @return [Numeric]
|
431
|
+
#
|
432
|
+
def length_of(attribute)
|
433
|
+
value = send(attribute)
|
434
|
+
|
435
|
+
return value ? value.length : 0
|
436
|
+
end
|
437
|
+
|
438
|
+
##
|
439
|
+
# Resets the list of definitions for the current RubyObject instance.
|
440
|
+
#
|
441
|
+
def clear!
|
442
|
+
@definitions = {
|
443
|
+
:local_variable => {},
|
444
|
+
:instance_variable => {},
|
445
|
+
:class_variable => {},
|
446
|
+
:global_variable => {},
|
447
|
+
:constant => {},
|
448
|
+
:method => {},
|
449
|
+
:instance_method => {},
|
450
|
+
:member => {},
|
451
|
+
:keyword => {}
|
452
|
+
}
|
453
|
+
end
|
454
|
+
|
455
|
+
##
|
456
|
+
# Merges the definitions object `other` into the current one.
|
457
|
+
#
|
458
|
+
# @param [RubyLint::Definition::RubyObject] other
|
459
|
+
#
|
460
|
+
def merge(other)
|
461
|
+
other.definitions.each do |type, values|
|
462
|
+
values.each do |name, definition|
|
463
|
+
definitions[type][name] = definition
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
##
|
469
|
+
# Copies all the definitions in `source` of type `type` into the current
|
470
|
+
# definitions object.
|
471
|
+
#
|
472
|
+
# @param [RubyLint::Definition::RubyObject] source
|
473
|
+
# @param [Symbol] source_type The type of definitions to copy from the
|
474
|
+
# source.
|
475
|
+
# @param [Symbol] target_type The type to store the definitions under,
|
476
|
+
# set to the `source_type` value by default.
|
477
|
+
#
|
478
|
+
def copy(source, source_type, target_type = source_type)
|
479
|
+
source.list(source_type).each do |definition|
|
480
|
+
add(target_type, definition.name, definition)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
##
|
485
|
+
# Returns an Array containing all the receivers of the current
|
486
|
+
# definition. These receivers are sorted from left to right. For example,
|
487
|
+
# assume the following:
|
488
|
+
#
|
489
|
+
# a.b.c
|
490
|
+
#
|
491
|
+
# In this case the return value would be as following:
|
492
|
+
#
|
493
|
+
# [a, b, c]
|
494
|
+
#
|
495
|
+
# @return [Array]
|
496
|
+
#
|
497
|
+
def receiver_path
|
498
|
+
receivers = []
|
499
|
+
source = self
|
500
|
+
|
501
|
+
while receiver = source.receiver
|
502
|
+
receivers << receiver
|
503
|
+
source = receiver
|
504
|
+
end
|
505
|
+
|
506
|
+
return receivers << self
|
507
|
+
end
|
508
|
+
|
509
|
+
##
|
510
|
+
# Creates a new definition object based on the current one that
|
511
|
+
# represents an instance of a Ruby value (instead of a class).
|
512
|
+
#
|
513
|
+
# @param [Hash] options Attributes to override in the new definition.
|
514
|
+
# @return [RubyLint::Definition::RubyObject]
|
515
|
+
#
|
516
|
+
def instance(options = {})
|
517
|
+
options = {
|
518
|
+
:name => name,
|
519
|
+
:type => type,
|
520
|
+
:instance_type => :instance,
|
521
|
+
:value => value,
|
522
|
+
:parents => [self]
|
523
|
+
}.merge(options)
|
524
|
+
|
525
|
+
return self.class.new(options)
|
526
|
+
end
|
527
|
+
|
528
|
+
##
|
529
|
+
# Returns `true` if the object was referenced more than once.
|
530
|
+
#
|
531
|
+
# @return [TrueClass|FalseClass]
|
532
|
+
#
|
533
|
+
def used?
|
534
|
+
return @reference_amount > 0
|
535
|
+
end
|
536
|
+
|
537
|
+
##
|
538
|
+
# Defines a new child constant.
|
539
|
+
#
|
540
|
+
# @example
|
541
|
+
# string.define_constant('NEWLINE')
|
542
|
+
#
|
543
|
+
# @param [String] name
|
544
|
+
# @return [RubyLint::Definition::RubyObject]
|
545
|
+
#
|
546
|
+
def define_constant(name, &block)
|
547
|
+
if name.include?(PATH_SEPARATOR)
|
548
|
+
path = name.split(PATH_SEPARATOR)
|
549
|
+
target = lookup_constant_path(path[0..-2])
|
550
|
+
definition = target.define_constant(path[-1], &block)
|
551
|
+
else
|
552
|
+
definition = add_child_definition(name, :constant, &block)
|
553
|
+
end
|
554
|
+
|
555
|
+
return definition
|
556
|
+
end
|
557
|
+
|
558
|
+
##
|
559
|
+
# Defines a new global variable in the current definition.
|
560
|
+
#
|
561
|
+
# @example
|
562
|
+
# string.define_global_variable('$name', '...')
|
563
|
+
#
|
564
|
+
# @param [String] name
|
565
|
+
# @param [Mixed] value
|
566
|
+
#
|
567
|
+
def define_global_variable(name, value = nil)
|
568
|
+
return add_child_definition(name, :global_variable, value)
|
569
|
+
end
|
570
|
+
|
571
|
+
##
|
572
|
+
# Defines a new class method.
|
573
|
+
#
|
574
|
+
# @example
|
575
|
+
# string.define_method(:new)
|
576
|
+
#
|
577
|
+
# @param [String] name
|
578
|
+
# @return [RubyLint::Definition::RubyMethod]
|
579
|
+
#
|
580
|
+
def define_method(name, &block)
|
581
|
+
return add_child_method(name, :method, &block)
|
582
|
+
end
|
583
|
+
|
584
|
+
##
|
585
|
+
# Defines a new instance method.
|
586
|
+
#
|
587
|
+
# @example
|
588
|
+
# string.define_instance_method(:gsub)
|
589
|
+
#
|
590
|
+
# @see RubyLint::Definition::RubyObject#define_method
|
591
|
+
#
|
592
|
+
def define_instance_method(name, &block)
|
593
|
+
return add_child_method(name, :instance_method, &block)
|
594
|
+
end
|
595
|
+
|
596
|
+
##
|
597
|
+
# Helper method that makes it easier to provide the two constructor
|
598
|
+
# methods `new` and `initialize`. The supplied block is yielded on both
|
599
|
+
# method definitions.
|
600
|
+
#
|
601
|
+
# @example
|
602
|
+
# some_object.define_constructors do |method|
|
603
|
+
# method.argument('name')
|
604
|
+
# end
|
605
|
+
#
|
606
|
+
def define_constructors(&block)
|
607
|
+
define_method('new', &block)
|
608
|
+
define_instance_method('initialize', &block)
|
609
|
+
end
|
610
|
+
|
611
|
+
##
|
612
|
+
# Adds the object(s) to the list of parent definitions.
|
613
|
+
#
|
614
|
+
# @param [Array] definitions
|
615
|
+
#
|
616
|
+
def inherits(*definitions)
|
617
|
+
self.parents += definitions
|
618
|
+
end
|
619
|
+
|
620
|
+
##
|
621
|
+
# Returns a pretty formatted String that shows some info about the
|
622
|
+
# current definition.
|
623
|
+
#
|
624
|
+
# @return [String]
|
625
|
+
#
|
626
|
+
def inspect
|
627
|
+
attributes = [
|
628
|
+
%Q(@name="#{name}"),
|
629
|
+
%Q(@type="#{type}"),
|
630
|
+
%Q(@instance_type="#{instance_type}")
|
631
|
+
]
|
632
|
+
|
633
|
+
# See <http://stackoverflow.com/a/2818916> for more info.
|
634
|
+
address = (object_id << 1).to_s(16)
|
635
|
+
|
636
|
+
return %Q(#<#{self.class}:0x#{address} #{attributes.join(' ')}>)
|
637
|
+
end
|
638
|
+
|
639
|
+
private
|
640
|
+
|
641
|
+
##
|
642
|
+
# Updates each parent definition if it has an existing definition for hte
|
643
|
+
# given type and name.
|
644
|
+
#
|
645
|
+
# @see #add
|
646
|
+
#
|
647
|
+
def update_parent_definitions(type, name, value)
|
648
|
+
parents.each do |parent|
|
649
|
+
parent.add(type, name, value) if parent.has_definition?(type, name)
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
##
|
654
|
+
# Adds a new child definition to the current definition.
|
655
|
+
#
|
656
|
+
# @param [String] name The name of the definition.
|
657
|
+
# @param [Symbol] type The definition type.
|
658
|
+
# @param [Mixed] value
|
659
|
+
# @return [RubyLint::Definition::RubyObject]
|
660
|
+
#
|
661
|
+
def add_child_definition(name, type, value = nil, &block)
|
662
|
+
definition = self.class.new(
|
663
|
+
:name => name,
|
664
|
+
:type => type,
|
665
|
+
:value => nil,
|
666
|
+
:parents => [self],
|
667
|
+
&block
|
668
|
+
)
|
669
|
+
|
670
|
+
add(definition.type, definition.name, definition)
|
671
|
+
|
672
|
+
return definition
|
673
|
+
end
|
674
|
+
|
675
|
+
##
|
676
|
+
# Adds a new child method to the current definition.
|
677
|
+
#
|
678
|
+
# @see RubyLint::Definition::RubyObject#add_child_definition
|
679
|
+
#
|
680
|
+
def add_child_method(name, type, &block)
|
681
|
+
definition = RubyMethod.new(
|
682
|
+
:name => name,
|
683
|
+
:type => :method,
|
684
|
+
:method_type => type,
|
685
|
+
:parents => [self],
|
686
|
+
&block
|
687
|
+
)
|
688
|
+
|
689
|
+
add(definition.method_type, definition.name, definition)
|
690
|
+
|
691
|
+
return definition
|
692
|
+
end
|
693
|
+
|
694
|
+
##
|
695
|
+
# Returns a boolean that indicates if the current definition type should
|
696
|
+
# be looked up in a parent definition.
|
697
|
+
#
|
698
|
+
# @param [Symbol] type The type of definition.
|
699
|
+
# @return [Trueclass|FalseClass]
|
700
|
+
#
|
701
|
+
def lookup_parent?(type)
|
702
|
+
return LOOKUP_PARENT.include?(type) && !parents.empty?
|
703
|
+
end
|
704
|
+
|
705
|
+
##
|
706
|
+
# Returns a Hash containing the default options.
|
707
|
+
#
|
708
|
+
# @return [Hash]
|
709
|
+
#
|
710
|
+
def default_options
|
711
|
+
return {
|
712
|
+
:update_parents => [],
|
713
|
+
:instance_type => :class,
|
714
|
+
:parents => [],
|
715
|
+
:receiver => nil,
|
716
|
+
:reference_amount => 0,
|
717
|
+
:value => nil
|
718
|
+
}
|
719
|
+
end
|
720
|
+
|
721
|
+
##
|
722
|
+
# Casts the type and name of data to look up to the correct values.
|
723
|
+
#
|
724
|
+
# @param [#to_sym] type
|
725
|
+
# @param [#to_s] name
|
726
|
+
# @return [Array]
|
727
|
+
#
|
728
|
+
def prepare_lookup(type, name)
|
729
|
+
return prepare_type(type), prepare_name(name)
|
730
|
+
end
|
731
|
+
|
732
|
+
##
|
733
|
+
# Prepares the name of a definition.
|
734
|
+
#
|
735
|
+
# @param [#to_s] name
|
736
|
+
# @return [String]
|
737
|
+
#
|
738
|
+
def prepare_name(name)
|
739
|
+
name = name.to_s unless name.is_a?(String)
|
740
|
+
|
741
|
+
return name
|
742
|
+
end
|
743
|
+
|
744
|
+
##
|
745
|
+
# Prepares the data type name.
|
746
|
+
#
|
747
|
+
# @param [#to_sym] type
|
748
|
+
# @return [Symbol]
|
749
|
+
#
|
750
|
+
def prepare_type(type)
|
751
|
+
type = type.to_sym unless type.is_a?(Symbol)
|
752
|
+
|
753
|
+
return type
|
754
|
+
end
|
755
|
+
end # RubyObject
|
756
|
+
end # Definition
|
757
|
+
end # RubyLint
|