motion_blender 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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