motion_blender 0.1.7 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -0
- data/README.md +7 -7
- data/lib/motion_blender/analyzer.rb +1 -4
- data/lib/motion_blender/analyzer/evaluator.rb +43 -10
- data/lib/motion_blender/analyzer/original_finder.rb +26 -0
- data/lib/motion_blender/analyzer/parser.rb +9 -11
- data/lib/motion_blender/analyzer/require.rb +5 -0
- data/lib/motion_blender/config.rb +5 -1
- data/lib/motion_blender/rake_tasks.rb +15 -9
- data/lib/motion_blender/version.rb +1 -1
- data/motion/motion_blender/ext/require_suppressor.rb +3 -0
- metadata +3 -3
- data/lib/motion_blender/analyzer/hooker.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79e7438cc7769076e46b9ad288b4f54fa75c53d5
|
4
|
+
data.tar.gz: f3e27ca0d88e10e203e4144ba61dc89a5aeffc58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3578fd948e8db4018cf866376c90aa1ad0bbf23533d85591f75711e4862e8492d741dd42265c9c00dc8982bf0f31db7ca37b2ba0e40a520de528a88cfa9c6aaf
|
7
|
+
data.tar.gz: 0099a52ca69ddfbd9b3c24aadf2bb4760eb02cfd2b4f07550e212bad14f2bbbacb838812dfb05e5480bc07fd09f8a7e74c70fa48245d8756615965c5e7a4d6e9
|
data/.rubocop.yml
CHANGED
@@ -61,6 +61,11 @@ Style/Lambda:
|
|
61
61
|
Style/MethodDefParentheses:
|
62
62
|
EnforcedStyle: require_no_parentheses
|
63
63
|
|
64
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
65
|
+
Style/MethodName:
|
66
|
+
Exclude:
|
67
|
+
- 'motion/motion_blender/**/*.rb'
|
68
|
+
|
64
69
|
# Cop supports --auto-correct.
|
65
70
|
Style/MultilineBlockLayout:
|
66
71
|
Exclude:
|
data/README.md
CHANGED
@@ -82,11 +82,11 @@ To require this *motion_hoge* makes an application or a gem to load functionalit
|
|
82
82
|
`motion_blender` itself is excepted for analyzing,
|
83
83
|
so don't worry to require `motion_blender` in *incept*-ed files.
|
84
84
|
|
85
|
-
###
|
85
|
+
### Parsing
|
86
86
|
|
87
|
-
|
87
|
+
It parses `require` statements properly in almost all the common cases.
|
88
88
|
|
89
|
-
|
89
|
+
Argument can be a string or an eval-able expression:
|
90
90
|
|
91
91
|
```ruby
|
92
92
|
# Good
|
@@ -103,10 +103,10 @@ Dir.glob('lib/**/*.rb').each { |path| require path }
|
|
103
103
|
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each { |file| require file }
|
104
104
|
```
|
105
105
|
|
106
|
-
|
106
|
+
Takes care of rescue clause:
|
107
107
|
|
108
108
|
```ruby
|
109
|
-
#
|
109
|
+
# Good
|
110
110
|
begin
|
111
111
|
require 'may_not_exist'
|
112
112
|
rescue LoadError
|
@@ -118,9 +118,9 @@ end
|
|
118
118
|
|
119
119
|
In the RubyMotion application's Rakefile, `motion_blender` is to be required, typically via `Bundler.require`.
|
120
120
|
Then it hooks `build` tasks.
|
121
|
-
You can hit `rake -P` and see `motion_blender:
|
121
|
+
You can hit `rake -P` and see `motion_blender:apply` task is hooked.
|
122
122
|
|
123
|
-
|
123
|
+
In apply task, MotionBlender runs analyzer on all `Motion::Project::Config#files`.
|
124
124
|
It uses [parser](https://github.com/whitequark/parser) and follows all `require` and `require_relative`.
|
125
125
|
After that, add the newly encountered files to the head of `Motion::Project::Config#files` and put file dependencies to `Motion::Project::Config#dependencies`.
|
126
126
|
|
@@ -5,17 +5,15 @@ require 'motion_blender/analyzer/parser'
|
|
5
5
|
module MotionBlender
|
6
6
|
class Analyzer
|
7
7
|
attr_reader :files, :dependencies
|
8
|
-
attr_accessor :exclude_files
|
9
8
|
|
10
9
|
def initialize
|
11
10
|
@analyzed_files = Set.new
|
12
|
-
@exclude_files = Set.new
|
13
11
|
@files = []
|
14
12
|
@dependencies = {}
|
15
13
|
end
|
16
14
|
|
17
15
|
def analyze file, backtrace = []
|
18
|
-
return if
|
16
|
+
return if MotionBlender.config.excepted_files.include? file
|
19
17
|
return if @analyzed_files.include? file
|
20
18
|
@analyzed_files << file
|
21
19
|
|
@@ -33,7 +31,6 @@ module MotionBlender
|
|
33
31
|
|
34
32
|
def parse file, backtrace
|
35
33
|
parser = Parser.new file
|
36
|
-
parser.exclude_files = @exclude_files
|
37
34
|
begin
|
38
35
|
parser.run_callbacks :parse do
|
39
36
|
parser.parse
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'motion_blender/analyzer/require'
|
2
|
+
require 'motion_blender/analyzer/original_finder'
|
3
|
+
|
1
4
|
module MotionBlender
|
2
5
|
class Analyzer
|
3
6
|
class Evaluator
|
@@ -13,23 +16,53 @@ module MotionBlender
|
|
13
16
|
def parse_args
|
14
17
|
extractor = create_extractor
|
15
18
|
extractor.instance_eval(@ast.loc.expression.source, @file)
|
16
|
-
extractor.instance_eval { @
|
17
|
-
rescue
|
18
|
-
|
19
|
+
extractor.instance_eval { @_args || [] }
|
20
|
+
rescue ScriptError => err
|
21
|
+
recover_from_script_error err
|
22
|
+
rescue StandardError => err
|
23
|
+
recover_from_standard_error err
|
24
|
+
end
|
25
|
+
|
26
|
+
def recover_from_script_error err
|
27
|
+
i = @stack.find_index { |ast| ast.type == :rescue }
|
28
|
+
if i && i > 0
|
29
|
+
stack = @stack[0..(i - 1)]
|
19
30
|
Evaluator.new(@file, stack.last, stack[0..-2], @method).parse_args
|
20
31
|
else
|
21
|
-
|
22
|
-
|
32
|
+
fail LoadError, err.message
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def recover_from_standard_error err
|
37
|
+
if @stack.any?
|
38
|
+
Evaluator.new(@file, @stack.last, @stack[0..-2], @method).parse_args
|
39
|
+
else
|
40
|
+
fail LoadError, err.message
|
23
41
|
end
|
24
42
|
end
|
25
43
|
|
26
44
|
def create_extractor
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
45
|
+
file = @file
|
46
|
+
extractor = Evaluator.extractor_for(@method).new
|
47
|
+
extractor.instance_eval { @_file = file }
|
48
|
+
extractor
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.extractor_for method
|
52
|
+
@extractor_classes ||= {}
|
53
|
+
@extractor_classes[method] ||= Class.new do
|
54
|
+
define_method method do |arg|
|
55
|
+
req = Require.new(@_file, method, arg)
|
56
|
+
unless req.excluded?
|
57
|
+
@_args ||= []
|
58
|
+
@_args << req
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
define_method :__ORIGINAL__ do
|
63
|
+
OriginalFinder.new(@_file).find
|
64
|
+
end
|
31
65
|
end
|
32
|
-
obj
|
33
66
|
end
|
34
67
|
end
|
35
68
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MotionBlender
|
2
|
+
class Analyzer
|
3
|
+
class OriginalFinder
|
4
|
+
attr_reader :file, :original
|
5
|
+
|
6
|
+
def initialize file
|
7
|
+
@file = file
|
8
|
+
end
|
9
|
+
|
10
|
+
def find
|
11
|
+
dir = MotionBlender.config.motion_dirs.find { |d| @file.start_with? d }
|
12
|
+
fail 'not found in motion_dirs' unless dir
|
13
|
+
arg = Pathname.new(@file).relative_path_from(Pathname.new(dir))
|
14
|
+
@original = candidates_for(arg).find(&:file?).try(&:to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
def candidates_for arg
|
18
|
+
Enumerator.new do |y|
|
19
|
+
$LOAD_PATH.each do |dir|
|
20
|
+
y << Pathname.new(dir).join(arg)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,7 +3,6 @@ require 'active_support'
|
|
3
3
|
require 'active_support/callbacks'
|
4
4
|
|
5
5
|
require 'motion_blender/analyzer/evaluator'
|
6
|
-
require 'motion_blender/analyzer/require'
|
7
6
|
|
8
7
|
module MotionBlender
|
9
8
|
class Analyzer
|
@@ -14,7 +13,6 @@ module MotionBlender
|
|
14
13
|
REQUIREMENT_TOKENS = %i(motion_require require_relative require)
|
15
14
|
|
16
15
|
attr_reader :file, :requires, :last_trace
|
17
|
-
attr_accessor :exclude_files
|
18
16
|
|
19
17
|
def initialize file
|
20
18
|
@file = file.to_s
|
@@ -27,16 +25,8 @@ module MotionBlender
|
|
27
25
|
end
|
28
26
|
|
29
27
|
def traverse ast, stack = []
|
30
|
-
@exclude_files ||= Set.new
|
31
28
|
if require_command?(ast)
|
32
|
-
|
33
|
-
Evaluator.new(@file, ast, stack).parse_args.each do |arg|
|
34
|
-
req = Require.new(@file, ast.children[1], arg)
|
35
|
-
next if @exclude_files.include? req.arg
|
36
|
-
next if @exclude_files.include? req.file
|
37
|
-
req.trace = @last_trace
|
38
|
-
@requires << req
|
39
|
-
end
|
29
|
+
evaluate ast, stack
|
40
30
|
elsif !raketime_block?(ast)
|
41
31
|
ast.children
|
42
32
|
.select { |node| node.is_a?(::Parser::AST::Node) }
|
@@ -44,6 +34,14 @@ module MotionBlender
|
|
44
34
|
end
|
45
35
|
end
|
46
36
|
|
37
|
+
def evaluate ast, stack
|
38
|
+
@last_trace = trace_for ast
|
39
|
+
Evaluator.new(@file, ast, stack).parse_args.each do |req|
|
40
|
+
req.trace = @last_trace
|
41
|
+
@requires << req
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
47
45
|
def require_command? ast
|
48
46
|
(ast.type == :send) && REQUIREMENT_TOKENS.include?(ast.children[1])
|
49
47
|
end
|
@@ -58,6 +58,11 @@ module MotionBlender
|
|
58
58
|
def match? arg_or_file
|
59
59
|
arg == arg_or_file || file == arg_or_file
|
60
60
|
end
|
61
|
+
|
62
|
+
def excluded?
|
63
|
+
MotionBlender.config.builtin_features.include?(arg) ||
|
64
|
+
MotionBlender.config.excepted_files.include?(file)
|
65
|
+
end
|
61
66
|
end
|
62
67
|
end
|
63
68
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module MotionBlender
|
2
4
|
class Config
|
3
5
|
attr_reader :incepted_files, :excepted_files, :motion_dirs
|
6
|
+
attr_reader :builtin_features
|
4
7
|
|
5
8
|
def initialize
|
6
9
|
@incepted_files = []
|
7
|
-
@excepted_files =
|
10
|
+
@excepted_files = Set.new
|
8
11
|
@motion_dirs = []
|
12
|
+
@builtin_features = Set.new %w(bigdecimal rational date thread)
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rake'
|
2
|
+
require 'yaml'
|
2
3
|
require 'motion_blender/config'
|
3
4
|
require 'motion_blender/analyzer'
|
4
5
|
|
@@ -10,16 +11,15 @@ module MotionBlender
|
|
10
11
|
|
11
12
|
def analyze
|
12
13
|
analyzer = Analyzer.new
|
13
|
-
analyzer.exclude_files += builtin_features + config.excepted_files
|
14
|
-
|
15
14
|
files = config.incepted_files + Motion::Project::App.config.files
|
16
15
|
files.flatten.each do |file|
|
17
16
|
analyzer.analyze file
|
18
17
|
end
|
19
|
-
|
18
|
+
analyzer
|
20
19
|
end
|
21
20
|
|
22
|
-
def apply
|
21
|
+
def apply
|
22
|
+
analyzer = analyze
|
23
23
|
Motion::Project::App.setup do |app|
|
24
24
|
new_files = analyzer.files - app.files
|
25
25
|
app.exclude_from_detect_dependencies += new_files
|
@@ -29,21 +29,27 @@ module MotionBlender
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
32
|
+
def dump
|
33
|
+
analyzer = analyze
|
34
|
+
YAML.dump %w(files dependencies).map { |k| [k, analyzer.send(k)] }.to_h
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
39
|
namespace :motion_blender do
|
39
|
-
task :
|
40
|
+
task :apply do
|
40
41
|
MotionBlender.on_parse do |parser|
|
41
42
|
Motion::Project::App.info('Analyze', parser.file)
|
42
43
|
end
|
43
|
-
MotionBlender::RakeTasks.new.
|
44
|
+
MotionBlender::RakeTasks.new.apply
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'Dump analyzed files and dependencies'
|
48
|
+
task :dump do
|
49
|
+
puts MotionBlender::RakeTasks.new.dump
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
47
53
|
%w(build:simulator build:device).each do |t|
|
48
|
-
task t => 'motion_blender:
|
54
|
+
task t => 'motion_blender:apply'
|
49
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion_blender
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kayhide
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -228,7 +228,7 @@ files:
|
|
228
228
|
- lib/motion_blender.rb
|
229
229
|
- lib/motion_blender/analyzer.rb
|
230
230
|
- lib/motion_blender/analyzer/evaluator.rb
|
231
|
-
- lib/motion_blender/analyzer/
|
231
|
+
- lib/motion_blender/analyzer/original_finder.rb
|
232
232
|
- lib/motion_blender/analyzer/parser.rb
|
233
233
|
- lib/motion_blender/analyzer/require.rb
|
234
234
|
- lib/motion_blender/callbacks.rb
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module MotionBlender
|
2
|
-
class Analyzer
|
3
|
-
module Hooker
|
4
|
-
module_function
|
5
|
-
|
6
|
-
def active?
|
7
|
-
!!@active
|
8
|
-
end
|
9
|
-
|
10
|
-
def activate
|
11
|
-
@active = true
|
12
|
-
end
|
13
|
-
|
14
|
-
def deactivate
|
15
|
-
@active = false
|
16
|
-
end
|
17
|
-
|
18
|
-
def requires
|
19
|
-
@requires ||= Hash.new { |hash, key| hash[key] = [] }
|
20
|
-
end
|
21
|
-
|
22
|
-
def clear
|
23
|
-
requires.clear
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
module Hooks
|
28
|
-
def require feature
|
29
|
-
if Hooker.active?
|
30
|
-
super
|
31
|
-
src = caller.first.split(':', 2).first
|
32
|
-
Hooker.requires[src] << feature
|
33
|
-
else
|
34
|
-
super
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
Object.send :include, MotionBlender::Analyzer::Hooks
|