-
Notifications
You must be signed in to change notification settings - Fork 25
/
Rakefile
183 lines (150 loc) · 5.7 KB
/
Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
require 'erb'
HERE = File.expand_path(File.dirname __FILE__)
GWT = "#{HERE}/BigDecimalApp"
GWT_SRC = "#{GWT}/src/com/iriscouch/gwtapp/client"
CJS_DIR = "#{HERE}/lib"
JS_BUILD = "#{HERE}/build/out.js"
CJS_PATH = "#{CJS_DIR}/bigdecimal.js"
task :default => :bigdecimal
directory CJS_DIR
java_sources = %w[ RoundingMode MathContext BigInteger BigDecimal BigDecimalApp ]
java_sources.each do |class_name|
java_source_path = "#{GWT_SRC}/#{class_name}.java"
file JS_BUILD => java_source_path
file java_source_path => "#{java_source_path}.erb" do |task|
erb_path = task.prerequisites.first
java_path = task.name
src = ERB.new(File.new(erb_path).read)
java = File.new(java_path, 'w')
java.write(src.result(binding))
java.close
puts "#{class_name}.java.erb => #{class_name}.java"
end
end
file JS_BUILD => CJS_DIR do |task|
# Build the base GWT library.
Dir.chdir GWT do
sh 'ant build' unless ENV['skip_ant']
end
gwt_js = Dir.glob("#{GWT}/war/gwtapp/#{'?' * 32}.cache.js").last
puts "Using compiled JS: #{gwt_js}"
gwt_source = File.new(gwt_js).read
File.new(task.name, 'w').write(gwt_source)
puts "#{gwt_js} => #{task.name}"
end
file CJS_PATH => [JS_BUILD, "commonjs_wrapper.js.erb"] do |task|
gwt_source = File.new(JS_BUILD).read
# Insert the code required to initialize the library. This is text manipulation to reach inside
# a function closure. It would be nice to switch to UglifyJS.
loader = "gwtOnLoad(null, 'ModuleName', 'moduleBase');"
gwt_source.gsub! /(\}\)\(\);)$/, "\n#{loader}\n\\1"
wrapper_src = File.new("commonjs_wrapper.js.erb").read
js = ERB.new wrapper_src
File.new(task.name, 'w').write(js.result binding)
puts "Generated #{File.basename task.name}"
end
desc 'Build CommonJS BigDecimal library'
task :bigdecimal => CJS_PATH
desc 'Push a demo BigDecimal Couch app'
task :couchapp => [CJS_PATH, "#{HERE}/CouchDB/demo.js"] do
couchapp = "#{HERE}/node_modules/.bin/couchapp"
raise "Can't find command #{couchapp}, did you 'npm install --dev'?" unless File.exist?(couchapp)
raise "Please specify a url parameter, e.g. url=http://admin:secret@example.iriscouch.com/demo" unless ENV['url']
sh couchapp, "push", "#{HERE}/CouchDB/demo.js", ENV['url']
url = ENV['url']
url = url.sub /\/+$/, ""
url = url.sub /^(https?):\/\/.*?:.*?@(.*)$/, "\\1://\\2"
puts ""
puts "Demo URL: #{url}/_design/bigdecimal/_show/ui"
end
desc 'Clean up'
task :clean do
sh "rm -rfv #{CJS_DIR} #{JS_BUILD} #{GWT_SRC}/Big*.java #{GWT_SRC}/MathContext.java #{GWT_SRC}/RoundingMode.java"
end
desc 'Show how to tag a revision'
task :tag do
puts <<EOT
How to Tag a Release
====================
I do not like generated code being managed by Git. However that is useful
when people download tarballs from GitHub, etc. So the idea is to have a
revision "spur" off the development line which only generates the code
and commits the tag.
1. Confirm the repo is clean
2. rake clean && rake
3. git add -f #{CJS_PATH} && git commit -m "Code release"
4. ver="vX.Y.Z" # Set this to something.
5. git tag -a -m "Tag release" "$ver"
6. git push origin "$ver:/refs/tags/$ver"
7. npm publish
8. Edit package.json and bump the version
9. git rm #{CJS_PATH}
10. git commit -m 'Working on <new version>'
EOT
end
#
# Helpers
#
def wrap(return_type, name, *signatures)
# When there is no ambiguity (i.e. only one method signature) just wrap it directly.
return wrap_nosigs(return_type, name, *signatures) if signatures.length <= 1
# Use the call_signatures system to call the correct Java method and return it back to JS.
lines = []
lines << "public #{return_type} #{name}_va(JsArgs args) {"
lines << "#{return_type} result;"
lines << "// return_type.to_s[0..2] = #{return_type.to_s[0..2]}"
if return_type.to_s[0..2] != 'Big'
call = "result = super.#{name}"
else
lines << "java.math.#{return_type} interim;"
call = "interim = super.#{name}"
end
lines << call_signatures('args', call, *signatures)
lines << "result = new #{return_type}(interim);" if return_type.to_s[0..2] == 'Big'
lines << "return result;"
lines << "}"
return lines.join("\n")
end
def wrap_nosigs(return_type, name, *param_types)
formal = []; actual = []
param_types.each_with_index do |param_type, a|
formal.push "#{param_type} var#{a}"
actual.push %w[ MathContext RoundingMode ].include?(param_type.to_s) ? "new java.math.#{param_type}(var#{a}.toString())" : "var#{a}"
end
call = "super.#{name}(#{actual.join ', '})"
expr = call
#expr = "new #{return_type}(#{call})" if return_type.to_s[0..2] == 'Big'
expr = "new #{return_type}(#{call})" if %w[ BigInteger BigDecimal MathContext RoundingMode ].include?(return_type.to_s)
"public #{return_type} #{name}(#{formal.join ', '}) { return #{expr}; }"
end
def call_signatures(args, expression, *signatures)
lines = []
lines << "String sig = JsArgs.signature(#{args});"
signatures.each_with_index do |sig, a|
js_types = []
param_types = []
sig.to_s.split.each do |param, a|
if %w[ int double ].include? param
js_types << 'number'
param_types << param.capitalize
elsif param == 'string'
js_types << 'string'
param_types << 'String'
elsif param == 'char_array'
js_types << 'array'
param_types << 'CharArray'
else
js_types << param
param_types << param
end
end
lines << "#{a == 0 ? 'if' : 'else if'}(sig == \"#{js_types.join ' '}\")"
actuals = []
param_types.each_with_index do |param_type, b|
actuals << "#{args}.get#{param_type}(#{b})"
end
lines << " #{expression}(#{actuals.join ', '});"
end
lines << "else throw new RuntimeException(\"Unknown call signature for #{expression}: \" + sig);"
return lines.join("\n");
end