piggly 1.2.1 → 2.0.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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +163 -0
  3. data/Rakefile +29 -15
  4. data/bin/piggly +4 -244
  5. data/lib/piggly.rb +19 -17
  6. data/lib/piggly/command.rb +9 -0
  7. data/lib/piggly/command/base.rb +148 -0
  8. data/lib/piggly/command/report.rb +162 -0
  9. data/lib/piggly/command/test.rb +157 -0
  10. data/lib/piggly/command/trace.rb +90 -0
  11. data/lib/piggly/command/untrace.rb +78 -0
  12. data/lib/piggly/compiler.rb +7 -5
  13. data/lib/piggly/compiler/cache_dir.rb +119 -0
  14. data/lib/piggly/compiler/coverage_report.rb +63 -0
  15. data/lib/piggly/compiler/trace_compiler.rb +105 -0
  16. data/lib/piggly/config.rb +47 -22
  17. data/lib/piggly/dumper.rb +9 -0
  18. data/lib/piggly/dumper/index.rb +121 -0
  19. data/lib/piggly/dumper/qualified_name.rb +36 -0
  20. data/lib/piggly/dumper/qualified_type.rb +81 -0
  21. data/lib/piggly/dumper/reified_procedure.rb +142 -0
  22. data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
  23. data/lib/piggly/installer.rb +84 -42
  24. data/lib/piggly/parser.rb +43 -49
  25. data/lib/piggly/parser/grammar.tt +289 -313
  26. data/lib/piggly/parser/nodes.rb +270 -211
  27. data/lib/piggly/parser/traversal.rb +35 -33
  28. data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
  29. data/lib/piggly/profile.rb +81 -60
  30. data/lib/piggly/reporter.rb +5 -18
  31. data/lib/piggly/reporter/base.rb +103 -0
  32. data/lib/piggly/reporter/html_dsl.rb +63 -0
  33. data/lib/piggly/reporter/index.rb +108 -0
  34. data/lib/piggly/reporter/procedure.rb +104 -0
  35. data/lib/piggly/reporter/resources/highlight.js +21 -0
  36. data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
  37. data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
  38. data/lib/piggly/tags.rb +280 -0
  39. data/lib/piggly/task.rb +191 -40
  40. data/lib/piggly/util.rb +8 -27
  41. data/lib/piggly/util/blankslate.rb +114 -0
  42. data/lib/piggly/util/cacheable.rb +19 -0
  43. data/lib/piggly/util/enumerable.rb +44 -0
  44. data/lib/piggly/util/file.rb +17 -0
  45. data/lib/piggly/util/process_queue.rb +96 -0
  46. data/lib/piggly/util/thunk.rb +39 -0
  47. data/lib/piggly/version.rb +8 -8
  48. data/spec/examples/compiler/cacheable_spec.rb +190 -0
  49. data/spec/examples/compiler/report_spec.rb +25 -0
  50. data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
  51. data/spec/examples/config_spec.rb +61 -0
  52. data/spec/examples/dumper/index_spec.rb +197 -0
  53. data/spec/examples/dumper/procedure_spec.rb +116 -0
  54. data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
  55. data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
  56. data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
  57. data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
  58. data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
  59. data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
  60. data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
  61. data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
  62. data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
  63. data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
  64. data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
  65. data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
  66. data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
  67. data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
  68. data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
  69. data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
  70. data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
  71. data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
  72. data/spec/examples/installer_spec.rb +59 -0
  73. data/spec/examples/parser/nodes_spec.rb +73 -0
  74. data/spec/examples/parser/traversal_spec.rb +14 -0
  75. data/spec/examples/parser_spec.rb +115 -0
  76. data/spec/examples/profile_spec.rb +153 -0
  77. data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
  78. data/spec/examples/reporter/html/index_spec.rb +0 -0
  79. data/spec/examples/reporter/html_spec.rb +1 -0
  80. data/spec/examples/reporter_spec.rb +0 -0
  81. data/spec/{compiler → examples}/tags_spec.rb +10 -10
  82. data/spec/examples/task_spec.rb +0 -0
  83. data/spec/examples/util/cacheable_spec.rb +41 -0
  84. data/spec/examples/util/enumerable_spec.rb +64 -0
  85. data/spec/examples/util/file_spec.rb +40 -0
  86. data/spec/examples/util/process_queue_spec.rb +16 -0
  87. data/spec/examples/util/thunk_spec.rb +58 -0
  88. data/spec/examples/version_spec.rb +0 -0
  89. data/spec/issues/007_spec.rb +25 -0
  90. data/spec/issues/008_spec.rb +73 -0
  91. data/spec/issues/018_spec.rb +25 -0
  92. data/spec/spec_helper.rb +253 -9
  93. metadata +136 -93
  94. data/README.markdown +0 -116
  95. data/lib/piggly/compiler/cache.rb +0 -151
  96. data/lib/piggly/compiler/pretty.rb +0 -67
  97. data/lib/piggly/compiler/queue.rb +0 -46
  98. data/lib/piggly/compiler/tags.rb +0 -244
  99. data/lib/piggly/compiler/trace.rb +0 -91
  100. data/lib/piggly/filecache.rb +0 -40
  101. data/lib/piggly/parser/parser.rb +0 -11794
  102. data/lib/piggly/reporter/html.rb +0 -207
  103. data/spec/compiler/cache_spec.rb +0 -9
  104. data/spec/compiler/pretty_spec.rb +0 -9
  105. data/spec/compiler/queue_spec.rb +0 -3
  106. data/spec/compiler/rewrite_spec.rb +0 -3
  107. data/spec/config_spec.rb +0 -58
  108. data/spec/filecache_spec.rb +0 -70
  109. data/spec/fixtures/snippets.sql +0 -158
  110. data/spec/grammar/tokens/lval_spec.rb +0 -50
  111. data/spec/parser_spec.rb +0 -8
  112. data/spec/profile_spec.rb +0 -5
@@ -1,64 +1,215 @@
1
- require 'rake'
2
- require 'rake/tasklib'
1
+ require "rake"
2
+ require "rake/tasklib"
3
+
4
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), ".."))
5
+ require "piggly"
3
6
 
4
7
  module Piggly
5
- class Task < Rake::TaskLib
8
+
9
+ class AbstractTask < Rake::TaskLib
6
10
  attr_accessor :name, # Name of the test task
7
- :libs, # List of paths added to $LOAD_PATH before running tests
8
- :test_files, # List of ruby test files to load
9
- :proc_files, # List of pl/pgsql stored procedures to compile
10
11
  :verbose,
11
- :warning, # Execute ruby -w if true
12
- :report_dir, # Where to store reports (default piggly/report)
13
- :cache_root, # Where to store compiler cache (default piggly/cache)
14
- :aggregate, # Accumulate coverage from the previous run (default false)
12
+ :ruby_opts
13
+
14
+ attr_accessor :procedures, # List of procedure names or regular expressions, match all by default
15
+ :cache_root, # Where to store cache data
15
16
  :piggly_opts,
16
- :piggly_path # Path to bin/piggly (default searches with ruby -S)
17
+ :piggly_path # Path to bin/piggly
17
18
 
18
19
  def initialize(name = :piggly)
19
- @name = name
20
- @libs = %w[]
21
- @verbose = false
22
- @warning = false
23
- @test_files = []
24
- @proc_files = []
25
- @ruby_opts = []
26
- @report_dir = 'piggly/report'
27
- @cache_root = 'piggly/cache'
28
- @piggly_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'piggly'))
29
- @piggly_opts = ''
30
- @aggregate = false
20
+ @name = name
21
+ @verbose = false
22
+ @ruby_opts = []
23
+
24
+ @procedures = []
25
+ @cache_root = nil
26
+ @piggly_path = File.expand_path("#{File.dirname(__FILE__)}/../../bin/piggly")
27
+ @piggly_opts = []
28
+
31
29
  yield self if block_given?
32
30
  define
33
31
  end
34
32
 
35
- # create tasks defined by this task lib
33
+ private
34
+
35
+ def quote(value)
36
+ case value
37
+ when Regexp
38
+ quote(value.inspect)
39
+ else
40
+ %{"#{value}"}
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ class TraceTask < AbstractTask
47
+ def initialize(name = :trace)
48
+ super(name)
49
+ end
50
+
51
+ private
52
+
36
53
  def define
37
- desc 'Run piggly tests' + (@name == :piggly ? '' : " for #{@name}")
54
+ desc 'Trace stored procedures'
38
55
  task @name do
39
- @piggly_opts << "--aggregate" if @aggregate
56
+ RakeFileUtils.verbose(@verbose) do
57
+ opts = []
58
+ opts << "trace"
59
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
60
+
61
+ case @procedures
62
+ when String then opts.concat(["--name", @procedures])
63
+ when Regexp then opts.concat(["--name", @procedures.inspect])
64
+ when Array
65
+ @procedures.each do |p|
66
+ case p
67
+ when String then opts.concat(["--name", p])
68
+ when Regexp then opts.concat(["--name", p.inspect])
69
+ end
70
+ end
71
+ end
72
+
73
+ opts.concat(@piggly_opts)
74
+ # ruby(opts.join(" "))
75
+ Command.main(opts)
76
+ end
77
+ end
78
+ end
79
+ end
40
80
 
81
+ class UntraceTask < AbstractTask
82
+ def initialize(name = :untrace)
83
+ super(name)
84
+ end
85
+
86
+ private
87
+
88
+ def define
89
+ desc 'Untrace stored procedures'
90
+ task @name do
41
91
  RakeFileUtils.verbose(@verbose) do
42
- run_code = (piggly_path.nil?) ? '-S piggly' : quote(piggly_path)
43
- opts = @ruby_opts.clone
44
- opts.push "-I#{Array(@libs).join(File::PATH_SEPARATOR)}"
45
- opts.push run_code
46
- opts.push '-w' if @warning
47
-
48
- ruby opts.join(' ') + ' ' +
49
- @piggly_opts + ' ' +
50
- %{-o #{quote @report_dir} } +
51
- %{-c #{quote @cache_root} } +
52
- proc_files.map{|s| %[-s "#{s}" ] }.join +
53
- test_files.map{|f| quote(f) }.join(' ')
92
+ # opts = @ruby_opts.clone
93
+ # opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
94
+ opts = []
95
+ opts << "untrace"
96
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
97
+
98
+ case @procedures
99
+ when String then opts.concat(["--name", @procedures])
100
+ when Regexp then opts.concat(["--name", @procedures.inspect])
101
+ when Array
102
+ @procedures.each do |p|
103
+ case p
104
+ when String then opts.concat(["--name", p])
105
+ when Regexp then opts.concat(["--name", p.inspect])
106
+ end
107
+ end
108
+ end
109
+
110
+ opts.concat(@piggly_opts)
111
+ # ruby(opts.join(" "))
112
+ Command.main(opts)
54
113
  end
114
+ end
115
+ end
116
+ end
117
+
118
+ class ReportTask < AbstractTask
119
+ attr_accessor :report_root, # Where to store reports (default piggly/report)
120
+ :accumulate, # Accumulate coverage from the previous run (default false)
121
+ :trace_file
55
122
 
123
+ def initialize(name = :report)
124
+ @accumulate = false
125
+ @trace_file = nil
126
+ @report_root = nil
127
+ super(name)
128
+ end
129
+
130
+ private
131
+
132
+ def define
133
+ desc 'Generate piggly report'
134
+ task @name do
135
+ RakeFileUtils.verbose(@verbose) do
136
+ # opts = @ruby_opts.clone
137
+ # opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
138
+ opts = []
139
+ opts << "report"
140
+ opts << "--accumulate" if @accumulate
141
+ opts.concat(["--trace-file", @trace_file])
142
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
143
+ opts.concat(["--report-root", @report_root]) if @report_root
144
+
145
+ case @procedures
146
+ when String then opts.concat(["--name", @procedures])
147
+ when Regexp then opts.concat(["--name", @procedures.inspect])
148
+ when Array
149
+ @procedures.each do |p|
150
+ case p
151
+ when String then opts.concat(["--name", p])
152
+ when Regexp then opts.concat(["--name", p.inspect])
153
+ end
154
+ end
155
+ end
156
+
157
+ opts.concat(@piggly_opts)
158
+ # ruby(opts.join(" "))
159
+ Command.main(opts)
160
+ end
56
161
  end
57
162
  end
163
+ end
164
+
165
+ class TestTask < AbstractTask
166
+ attr_accessor :test_files, # List of ruby test files to load
167
+ :report_root, # Where to store reports (default piggly/report)
168
+ :accumulate # Accumulate coverage from the previous run (default false)
58
169
 
59
- def quote(string)
60
- %{"#{string}"}
170
+ def initialize(name = :piggly)
171
+ @report_root = nil
172
+ @test_files = []
173
+ @accumulate = false
174
+ super(name)
61
175
  end
62
176
 
177
+ private
178
+
179
+ def define
180
+ desc 'Run piggly tests' + (@name == :piggly ? '' : " for #{@name}")
181
+ task @name do
182
+ RakeFileUtils.verbose(@verbose) do
183
+ opts = @ruby_opts.clone
184
+ opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
185
+ opts << "test"
186
+ opts << "--accumulate" if @accumulate
187
+ opts << "--cache-root #{quote @cache_root}" if @cache_root
188
+ opts << "--report-root #{quote @report_root}" if @report_root
189
+
190
+ case @procedures
191
+ when String then opts << "--name #{quote @procedures}"
192
+ when Regexp then opts << "--name #{quote @procedures.inspect}"
193
+ when Array
194
+ @procedures.each do |p|
195
+ case p
196
+ when String then opts << "--name #{quote p}"
197
+ when Regexp then opts << "--name #{quote p.inspect}"
198
+ end
199
+ end
200
+ end
201
+
202
+ opts.concat(@piggly_opts)
203
+
204
+ unless (@test_files || []).empty?
205
+ opts << "--"
206
+ opts.concat(@test_files.map{|x| quote(x) })
207
+ end
208
+
209
+ ruby(opts.join(" "))
210
+ end
211
+ end
212
+ end
63
213
  end
214
+
64
215
  end
@@ -1,28 +1,9 @@
1
- module Enumerable
2
-
3
- # Count number of elements, optionally filtered by a block
4
- def count
5
- if block_given?
6
- inject(0){|count, x| count + (yield(x) ? 1 : 0) }
7
- else
8
- size
9
- end
10
- end unless method_defined?(:count)
11
-
12
- # Sum elements, optionally transformed by a block
13
- def sum(init = 0)
14
- if block_given?
15
- inject(init){|sum, e| sum + yield(e) }
16
- else
17
- inject(init){|sum, e| sum + e }
18
- end
19
- end unless method_defined?(:sum)
20
-
21
- def group_by(collection = Hash.new{|h,k| h[k] = [] })
22
- inject(collection) do |hash, item|
23
- hash[yield(item)] << item
24
- hash
25
- end
26
- end unless method_defined?(:group_by)
27
-
1
+ module Piggly
2
+ module Util
3
+ autoload :ProcessQueue, "piggly/util/process_queue"
4
+ autoload :Thunk, "piggly/util/thunk"
5
+ autoload :Cacheable, "piggly/util/cacheable"
6
+ autoload :Enumerable, "piggly/util/enumerable"
7
+ autoload :File, "piggly/util/file"
8
+ end
28
9
  end
@@ -0,0 +1,114 @@
1
+ unless defined? BlankSlate
2
+ #--
3
+ # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ ######################################################################
12
+ # BlankSlate provides an abstract base class with no predefined
13
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
14
+ # BlankSlate is useful as a base class when writing classes that
15
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16
+ #
17
+ class BlankSlate
18
+ class << self
19
+
20
+ # Hide the method named +name+ in the BlankSlate class. Don't
21
+ # hide +instance_eval+ or any method beginning with "__".
22
+ def hide(name)
23
+ if instance_methods.include?(name.to_s) and
24
+ name !~ /^(__|instance_eval)/
25
+ @hidden_methods ||= {}
26
+ @hidden_methods[name.to_sym] = instance_method(name)
27
+ undef_method name
28
+ end
29
+ end
30
+
31
+ def find_hidden_method(name)
32
+ @hidden_methods ||= {}
33
+ @hidden_methods[name] || superclass.find_hidden_method(name)
34
+ end
35
+
36
+ # Redefine a previously hidden method so that it may be called on a blank
37
+ # slate object.
38
+ def reveal(name)
39
+ bound_method = nil
40
+ unbound_method = find_hidden_method(name)
41
+ fail "Don't know how to reveal method '#{name}'" unless unbound_method
42
+ define_method(name) do |*args|
43
+ bound_method ||= unbound_method.bind(self)
44
+ bound_method.call(*args)
45
+ end
46
+ end
47
+ end
48
+
49
+ instance_methods.each { |m| hide(m) }
50
+ end
51
+
52
+ ######################################################################
53
+ # Since Ruby is very dynamic, methods added to the ancestors of
54
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
55
+ # list of available BlankSlate methods. We handle this by defining a
56
+ # hook in the Object and Kernel classes that will hide any method
57
+ # defined after BlankSlate has been loaded.
58
+ #
59
+ module Kernel
60
+ class << self
61
+ alias_method :blank_slate_method_added, :method_added
62
+
63
+ # Detect method additions to Kernel and remove them in the
64
+ # BlankSlate class.
65
+ def method_added(name)
66
+ result = blank_slate_method_added(name)
67
+ return result if self != Kernel
68
+ BlankSlate.hide(name)
69
+ result
70
+ end
71
+ end
72
+ end
73
+
74
+ ######################################################################
75
+ # Same as above, except in Object.
76
+ #
77
+ class Object
78
+ class << self
79
+ alias_method :blank_slate_method_added, :method_added
80
+
81
+ # Detect method additions to Object and remove them in the
82
+ # BlankSlate class.
83
+ def method_added(name)
84
+ result = blank_slate_method_added(name)
85
+ return result if self != Object
86
+ BlankSlate.hide(name)
87
+ result
88
+ end
89
+
90
+ def find_hidden_method(name)
91
+ nil
92
+ end
93
+ end
94
+ end
95
+
96
+ ######################################################################
97
+ # Also, modules included into Object need to be scanned and have their
98
+ # instance methods removed from blank slate. In theory, modules
99
+ # included into Kernel would have to be removed as well, but a
100
+ # "feature" of Ruby prevents late includes into modules from being
101
+ # exposed in the first place.
102
+ #
103
+ class Module
104
+ alias blankslate_original_append_features append_features
105
+ def append_features(mod)
106
+ result = blankslate_original_append_features(mod)
107
+ return result if mod != Object
108
+ instance_methods.each do |name|
109
+ BlankSlate.hide(name)
110
+ end
111
+ result
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,19 @@
1
+ module Piggly
2
+ module Util
3
+ module Cacheable
4
+
5
+ def cache_path(file)
6
+ # Up to the last capitalized word of the class name
7
+ classdir = self.class.name[/^(?:.+::)?(.+?)([A-Z][^A-Z]+)?$/, 1]
8
+
9
+ # md5 the full path to prevent collisions
10
+ full = ::File.expand_path(file)
11
+ hash = Digest::MD5.hexdigest(::File.dirname(full))
12
+ base = ::File.basename(file)
13
+
14
+ @config.mkpath(::File.join(@config.cache_root, classdir), base)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ module Piggly
2
+ module Util
3
+ module Enumerable
4
+
5
+ # Count number of elements, optionally filtered by a block
6
+ def self.count(enum)
7
+ if block_given?
8
+ enum.inject(0){|count,e| yield(e) ? count + 1 : count }
9
+ else
10
+ enum.length
11
+ end
12
+ end
13
+
14
+ # Compute sum of elements, optionally transformed by a block
15
+ def self.sum(enum, default = 0, &block)
16
+ enum = enum.to_a
17
+ return default if enum.empty?
18
+
19
+ head, *tail = enum
20
+
21
+ if block_given?
22
+ tail.inject(yield(head)){|sum,e| sum + yield(e) }
23
+ else
24
+ tail.inject(head){|sum,e| sum + e }
25
+ end
26
+ end
27
+
28
+ # Collect an elements into disjoint sets, grouped by result of the block
29
+ def self.group_by(enum, collection = Hash.new{|h,k| h[k] = [] })
30
+ enum.inject(collection) do |hash, item|
31
+ hash[yield(item)] << item
32
+ hash
33
+ end
34
+ end
35
+
36
+ def self.index_by(enum, collection = Hash.new)
37
+ enum.inject(collection) do |hash, item|
38
+ hash.update(yield(item) => item)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end