motion_blender 0.2.1 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7121d843e2bcddd5273bebf2813494d561a19bcb
4
- data.tar.gz: c73a06ece8cc6fbd6abd0c4ea66a0d5042fd6b89
3
+ metadata.gz: d31c71624cf252cc727b8d45cf2a4bce2528f72d
4
+ data.tar.gz: 95f5637cd49eae8454f43a6c86dd76b8a23cd55a
5
5
  SHA512:
6
- metadata.gz: 15e84edf8cc830f2ba39332cca4c690e883a352c2bd4437ef567274ce55ec33ba2691262aca1dbaba758c11f47cf375a10fcb96171b4ea18cf6e236fca355db3
7
- data.tar.gz: e7fac9a8ea4c72eba203912e77ee78f51b3bf4346cd4a3767ee059a2439984fbd0a0bec74919cc8d5215f3e1c7f566b7de6d4991cc641b3eefb6c769acd798de
6
+ metadata.gz: 96d95574e04d3a78e216b2342ac79883805c5536321da913e8d24f4f5873d9794fd46402f59b18c136106c2f0551525bb5e4e158453ea77ce6172349d5299ace
7
+ data.tar.gz: 600d2675e5ea75eedd6b6e8cd55742b124837862de5abd5f00d6ba2e1e64c03f22a60fa77d21459172b6a2a4b57d2e544cd80689bdff1746b99df21ae69389e5
data/.rubocop.yml CHANGED
@@ -64,6 +64,7 @@ Style/MethodDefParentheses:
64
64
  # Configuration parameters: EnforcedStyle, SupportedStyles.
65
65
  Style/MethodName:
66
66
  Exclude:
67
+ - 'lib/motion_blender/analyzer/evaluator.rb'
67
68
  - 'motion/motion_blender/**/*.rb'
68
69
 
69
70
  # Cop supports --auto-correct.
@@ -1,3 +1,6 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+
1
4
  require 'motion_blender/version'
2
5
  require 'motion_blender/rake_tasks'
3
6
  require 'motion_blender/callbacks'
@@ -11,7 +11,6 @@ module MotionBlender
11
11
  @analyzed_files = Set.new
12
12
  @files = []
13
13
  @dependencies = {}
14
- @cache = Cache.new
15
14
  end
16
15
 
17
16
  def analyze file, backtrace = []
@@ -19,11 +18,9 @@ module MotionBlender
19
18
  return if @analyzed_files.include? file
20
19
  @analyzed_files << file
21
20
 
22
- requires = @cache.fetch(file) do
23
- parse file, backtrace
24
- end
21
+ requires = parse file, backtrace
25
22
 
26
- if requires.any?
23
+ if requires.present?
27
24
  @dependencies[file] = requires.map(&:file)
28
25
  @files = [*@files, file, *@dependencies[file]].uniq
29
26
  requires.each do |req|
@@ -1,45 +1,61 @@
1
1
  module MotionBlender
2
2
  class Analyzer
3
3
  class Cache
4
+ attr_reader :file, :hit
5
+ alias_method :hit?, :hit
6
+
7
+ def initialize file
8
+ @file = Pathname.new(file)
9
+ end
10
+
4
11
  def dir
5
12
  MotionBlender.config.cache_dir
6
13
  end
7
14
 
8
- def fetch file
15
+ def fetch
9
16
  return yield unless dir
10
- file = Pathname.new(file)
11
- cache = cache_file_for(file)
12
- if valid_cache?(file, cache)
13
- read cache
17
+
18
+ @hit = valid?
19
+ if @hit
20
+ read
14
21
  else
15
22
  content = yield
16
- write cache, content
23
+ write content
17
24
  end
18
25
  rescue YAML::Exception
19
- if cache.exist?
20
- cache.delete
21
- retry
22
- end
26
+ retry if delete
23
27
  raise
24
28
  end
25
29
 
26
- def read file
27
- YAML.load_file file
30
+ def read
31
+ YAML.load_file cache_file
28
32
  end
29
33
 
30
- def write file, content
31
- file.dirname.mkpath
32
- file.write YAML.dump(content)
34
+ def write content
35
+ if content.nil?
36
+ delete
37
+ else
38
+ cache_file.dirname.mkpath
39
+ cache_file.write YAML.dump(content)
40
+ end
33
41
  content
34
42
  end
35
43
 
36
- def valid_cache? file, cache
37
- cache.file? && file.mtime < cache.mtime
44
+ def delete
45
+ cache_file.exist? && cache_file.delete
46
+ end
47
+
48
+ def valid?
49
+ cache_file.file? && @file.mtime < cache_file.mtime
38
50
  end
39
51
 
40
- def cache_file_for file
41
- file = file.relative_path_from(Pathname.new('/')) if file.absolute?
42
- dir.join(file.to_s + '.yml')
52
+ def cache_file
53
+ @cache_file ||=
54
+ begin
55
+ path = @file
56
+ path = path.relative_path_from(Pathname.new('/')) if path.absolute?
57
+ dir.join(path.to_s + '.yml')
58
+ end
43
59
  end
44
60
  end
45
61
  end
@@ -1,22 +1,33 @@
1
+ require 'motion_blender/analyzer/source'
1
2
  require 'motion_blender/analyzer/require'
2
3
  require 'motion_blender/analyzer/original_finder'
3
4
 
4
5
  module MotionBlender
5
6
  class Analyzer
6
7
  class Evaluator
7
- attr_reader :file, :ast, :stack
8
+ attr_reader :source
9
+ attr_reader :trace, :requires
10
+ attr_reader :dynamic
11
+ alias_method :dynamic?, :dynamic
8
12
 
9
- def initialize file, ast, stack = [], method = nil
10
- @file = file
11
- @ast = ast
12
- @stack = stack
13
- @method = method || @ast.children[1]
13
+ def initialize source
14
+ @source = source
15
+ @trace = "#{source.file}:#{source.line}:in `#{source.method}'"
16
+ @requires = []
17
+ @dynamic = false
14
18
  end
15
19
 
16
- def parse_args
17
- extractor = create_extractor
18
- extractor.instance_eval(@ast.loc.expression.source, @file)
19
- extractor.instance_eval { @_args || [] }
20
+ def run
21
+ return if @source.evaluated?
22
+
23
+ @source.evaluated!
24
+ extractor = Extractor.new(@source.file)
25
+ extractor.instance_eval(@source.code, @source.file, @source.line)
26
+ @requires = extractor.instance_variable_get(:@_args) || []
27
+ @requires.each do |req|
28
+ req.trace = @trace
29
+ end
30
+ self
20
31
  rescue ScriptError => err
21
32
  recover_from_script_error err
22
33
  rescue StandardError => err
@@ -24,33 +35,26 @@ module MotionBlender
24
35
  end
25
36
 
26
37
  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)]
30
- Evaluator.new(@file, stack.last, stack[0..-2], @method).parse_args
31
- else
32
- fail LoadError, err.message
33
- end
38
+ @source = @source.parent while @source && !@source.type.rescue?
39
+ @source &&= @source.parent
40
+ fail LoadError, err.message unless @source
41
+ @dynamic = true
42
+ run
34
43
  end
35
44
 
36
45
  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
41
- end
46
+ @source = @source.parent
47
+ fail LoadError, err.message unless @source
48
+ @dynamic = true
49
+ run
42
50
  end
43
51
 
44
- def create_extractor
45
- file = @file
46
- extractor = Evaluator.extractor_for(@method).new
47
- extractor.instance_eval { @_file = file }
48
- extractor
49
- end
52
+ class Extractor
53
+ def initialize file
54
+ @_file = file
55
+ end
50
56
 
51
- def self.extractor_for method
52
- @extractor_classes ||= {}
53
- @extractor_classes[method] ||= Class.new do
57
+ Require::TOKENS.each do |method|
54
58
  define_method method do |arg|
55
59
  req = Require.new(@_file, method, arg)
56
60
  unless req.excluded?
@@ -58,10 +62,10 @@ module MotionBlender
58
62
  @_args << req
59
63
  end
60
64
  end
65
+ end
61
66
 
62
- define_method :__ORIGINAL__ do
63
- OriginalFinder.new(@_file).find
64
- end
67
+ def __ORIGINAL__
68
+ OriginalFinder.new(@_file).find
65
69
  end
66
70
  end
67
71
  end
@@ -2,7 +2,9 @@ require 'parser/current'
2
2
  require 'active_support'
3
3
  require 'active_support/callbacks'
4
4
 
5
+ require 'motion_blender/analyzer/source'
5
6
  require 'motion_blender/analyzer/evaluator'
7
+ require 'motion_blender/analyzer/require'
6
8
 
7
9
  module MotionBlender
8
10
  class Analyzer
@@ -10,49 +12,61 @@ module MotionBlender
10
12
  include ActiveSupport::Callbacks
11
13
  define_callbacks :parse
12
14
 
13
- REQUIREMENT_TOKENS = %i(motion_require require_relative require)
14
-
15
- attr_reader :file, :requires, :last_trace
15
+ attr_reader :file, :evaluators, :cache
16
16
 
17
17
  def initialize file
18
18
  @file = file.to_s
19
- @requires = []
19
+ @evaluators = []
20
20
  end
21
21
 
22
22
  def parse
23
- ast = ::Parser::CurrentRuby.parse(File.read(@file))
24
- traverse ast if ast
23
+ srcs = cache.fetch do
24
+ ast = ::Parser::CurrentRuby.parse_file(@file)
25
+ ast && traverse(Source.new(ast: ast))
26
+ if @evaluators.present? && @evaluators.none?(&:dynamic?)
27
+ @evaluators.map(&:source).map(&:attributes)
28
+ end
29
+ end
30
+ if srcs && cache.hit?
31
+ srcs.each do |attrs|
32
+ evaluate Source.new(attrs)
33
+ end
34
+ end
35
+ self
25
36
  end
26
37
 
27
- def traverse ast, stack = []
28
- if require_command?(ast)
29
- evaluate ast, stack
30
- elsif !raketime_block?(ast)
31
- ast.children
32
- .select { |node| node.is_a?(::Parser::AST::Node) }
33
- .each { |node| traverse node, [*stack, ast] }
34
- end
38
+ def cache
39
+ @cache ||= Cache.new @file
35
40
  end
36
41
 
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
+ def traverse source
43
+ if require_command?(source)
44
+ evaluate source
45
+ elsif !raketime_block?(source)
46
+ source.children.each { |src| traverse src }
42
47
  end
43
48
  end
44
49
 
45
- def require_command? ast
46
- (ast.type == :send) && REQUIREMENT_TOKENS.include?(ast.children[1])
50
+ def evaluate source
51
+ @evaluators << Evaluator.new(source)
52
+ @evaluators.last.run
53
+ end
54
+
55
+ def requires
56
+ @evaluators.map(&:requires).flatten
57
+ end
58
+
59
+ def last_trace
60
+ @evaluators.last.try :trace
47
61
  end
48
62
 
49
- def raketime_block? ast
50
- (ast.type == :block) &&
51
- (ast.children.first.loc.expression.source == 'MotionBlender.raketime')
63
+ def require_command? source
64
+ source.type.send? && Require.acceptable?(source.method)
52
65
  end
53
66
 
54
- def trace_for ast
55
- "#{@file}:#{ast.loc.line}:in `#{ast.children[1]}'"
67
+ def raketime_block? source
68
+ source.type.block? &&
69
+ (source.children.first.code == 'MotionBlender.raketime')
56
70
  end
57
71
  end
58
72
  end
@@ -7,6 +7,8 @@ module MotionBlender
7
7
  include ActiveSupport::Callbacks
8
8
  define_callbacks :require
9
9
 
10
+ TOKENS = %i(motion_require require_relative require)
11
+
10
12
  attr_accessor :loader, :method, :arg, :trace
11
13
 
12
14
  def initialize loader, method, arg
@@ -63,6 +65,10 @@ module MotionBlender
63
65
  MotionBlender.config.builtin_features.include?(arg) ||
64
66
  MotionBlender.config.excepted_files.include?(file)
65
67
  end
68
+
69
+ def self.acceptable? method
70
+ TOKENS.include?(method)
71
+ end
66
72
  end
67
73
  end
68
74
  end
@@ -0,0 +1,46 @@
1
+ module MotionBlender
2
+ class Analyzer
3
+ class Source
4
+ attr_reader :code, :file, :line, :parent, :type, :method, :ast
5
+ attr_reader :evaluated
6
+ alias_method :evaluated?, :evaluated
7
+
8
+ def initialize attrs = {}
9
+ @evaluated = false
10
+ ast = attrs.delete :ast
11
+ if ast
12
+ @code = ast.loc.expression.try(:source)
13
+ @file = ast.loc.expression.try(:source_buffer).try(:name)
14
+ @line = ast.loc.expression.try(:line)
15
+ @type = ast.type.to_s.inquiry
16
+ @method = @type.send? ? ast.children[1] : nil
17
+ @ast = ast
18
+ end
19
+ attrs.each do |k, v|
20
+ instance_variable_set "@#{k}", v
21
+ end
22
+ end
23
+
24
+ def evaluated!
25
+ @evaluated = true
26
+ end
27
+
28
+ def children
29
+ @children ||=
30
+ if @ast
31
+ @ast.children.grep(::Parser::AST::Node).map do |ast|
32
+ Source.new(ast: ast, parent: self)
33
+ end
34
+ else
35
+ []
36
+ end
37
+ end
38
+
39
+ def attributes
40
+ %w(code file line type method).map do |k|
41
+ [k, instance_variable_get("@#{k}")]
42
+ end.to_h.as_json
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module MotionBlender
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ['lib']
21
21
 
22
22
  spec.add_runtime_dependency 'parser'
23
+ spec.add_runtime_dependency 'activesupport', '~> 4.2'
23
24
  spec.add_development_dependency 'bundler', '~> 1.10'
24
25
  spec.add_development_dependency 'rake', '~> 10.0'
25
26
  spec.add_development_dependency 'rspec'
@@ -32,5 +33,4 @@ Gem::Specification.new do |spec|
32
33
  spec.add_development_dependency 'guard-rubocop'
33
34
  spec.add_development_dependency 'simplecov'
34
35
  spec.add_development_dependency 'simplecov-gem-profile'
35
- spec.add_development_dependency 'activesupport', '~> 4.2'
36
36
  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.2.1
4
+ version: 0.2.2
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-31 00:00:00.000000000 Z
11
+ date: 2015-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -192,20 +206,6 @@ dependencies:
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
208
  version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: activesupport
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '4.2'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: '4.2'
209
209
  description: MotionBlender loads ruby gems for RubyMotion
210
210
  email:
211
211
  - kayhide@gmail.com
@@ -232,6 +232,7 @@ files:
232
232
  - lib/motion_blender/analyzer/original_finder.rb
233
233
  - lib/motion_blender/analyzer/parser.rb
234
234
  - lib/motion_blender/analyzer/require.rb
235
+ - lib/motion_blender/analyzer/source.rb
235
236
  - lib/motion_blender/callbacks.rb
236
237
  - lib/motion_blender/config.rb
237
238
  - lib/motion_blender/ext.rb