ruby-lint 0.0.2 → 0.0.3
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.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
|