fcshd 0.3.1 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Makefile +8 -2
- data/bin/fcshc +109 -37
- data/bin/fcshd +6 -0
- data/lib/fcshd/compiler.rb +1 -1
- data/lib/fcshd/problem.rb +3 -149
- data/lib/fcshd/server.rb +2 -2
- data/lib/fcshd/source-location.rb +4 -16
- data/lib/fcshd/transcript-item.rb +154 -0
- data/lib/fcshd/transcript-parser.rb +65 -0
- data/lib/fcshd/transcript.rb +35 -0
- data/lib/fcshd/version.rb +1 -1
- data/lib/fcshd.rb +9 -2
- metadata +8 -8
- data/lib/fcshd/compiler-output-writer.rb +0 -19
- data/lib/fcshd/compiler-output.rb +0 -91
data/Makefile
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
version=$(shell ruby -r lib/fcshd/version -e 'print FCSHD::VERSION')
|
2
|
+
|
3
|
+
default: install
|
4
|
+
|
1
5
|
build:
|
2
6
|
gem build fcshd.gemspec
|
7
|
+
install: build
|
8
|
+
sudo gem install fcshd-${version}.gem
|
9
|
+
push: build
|
10
|
+
gem push fcshd-${version}.gem
|
3
11
|
clean:
|
4
12
|
rm *.gem
|
5
|
-
push: build
|
6
|
-
gem push fcshd-$(shell ruby -r lib/fcshd/version -e 'print FCSHD::VERSION').gem
|
data/bin/fcshc
CHANGED
@@ -16,82 +16,159 @@ def die(message)
|
|
16
16
|
exit 1
|
17
17
|
end
|
18
18
|
|
19
|
-
$
|
20
|
-
$
|
19
|
+
$output_file = nil
|
20
|
+
$source_files = []
|
21
|
+
$library_files = []
|
22
|
+
$directories = []
|
23
|
+
$production = false
|
21
24
|
$extra_arguments = []
|
25
|
+
$verbose = false
|
26
|
+
$dry_run = false
|
22
27
|
|
23
28
|
OptionParser.new do |parser|
|
24
|
-
parser.banner =
|
29
|
+
parser.banner = <<EOF
|
30
|
+
Usage: fcshc MAIN.[as|mxml] [SRCDIR|SWCDIR|SWC]... [-o OUTPUT.swf]
|
31
|
+
fcshc -o OUTPUT.swc [SRCDIR|SWCDIR|SWC]...
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
To compile an SWF, name the main application source file, then any
|
34
|
+
additional source directories, SWC directories, or SWC files.
|
35
|
+
|
36
|
+
To compile an SWC using `compc', you must provide the `-o' option, and
|
37
|
+
then at least one source directory, SWC directory, or SWC file.
|
38
|
+
|
39
|
+
To pass extra arguments, use e.g. `-X -include-file -X NAME -X FILE'.
|
40
|
+
|
41
|
+
EOF
|
42
|
+
|
43
|
+
parser.on("-o", "--output OUTPUT.[swf|swc]", "Name of the resulting binary") do |value|
|
44
|
+
$output_file = File.expand_path(value)
|
28
45
|
end
|
29
46
|
|
30
|
-
parser.on("-
|
31
|
-
$extra_arguments <<
|
47
|
+
parser.on("-X", "--extra-argument ARGUMENT", "Pass ARGUMENT to the compiler") do |value|
|
48
|
+
$extra_arguments << value
|
32
49
|
end
|
33
50
|
|
34
|
-
parser.on("
|
51
|
+
parser.on("-p", "--production", "Leave out debugging metadata") do
|
52
|
+
$production = true
|
53
|
+
end
|
54
|
+
|
55
|
+
parser.on("--static-rsls", "Use static linking for RSLs") do
|
56
|
+
$extra_arguments << "-static-link-runtime-shared-libraries=true"
|
57
|
+
end
|
58
|
+
|
59
|
+
parser.on("--no-rsls", "Remove all runtime shared libraries") do
|
35
60
|
$extra_arguments << "-runtime-shared-library-path="
|
36
61
|
end
|
37
62
|
|
63
|
+
parser.separator ""
|
64
|
+
|
65
|
+
parser.on("-3", "--flex-3", "Use -compatibility-version=3") do |value|
|
66
|
+
$extra_arguments << "-compatibility-version=3"
|
67
|
+
end
|
68
|
+
|
38
69
|
parser.on("--halo", "Use the Halo theme") do
|
39
70
|
die "must set $FLEX_HOME to use --halo option" if not FlexHome.known?
|
40
71
|
$extra_arguments << "-theme=#{FlexHome.halo_swc}"
|
41
72
|
end
|
42
73
|
|
43
|
-
parser.
|
44
|
-
|
74
|
+
parser.separator ""
|
75
|
+
|
76
|
+
parser.on("-n", "--dry-run", "Only print the compiler command") do
|
77
|
+
$dry_run = true
|
45
78
|
end
|
46
79
|
|
47
|
-
parser.on("
|
80
|
+
parser.on("--verbose", "Also print the compiler command") do
|
48
81
|
$verbose = true
|
49
82
|
end
|
83
|
+
|
84
|
+
parser.on("-v", "--version", "Show `fcshc #{FCSHD::VERSION}'") do
|
85
|
+
puts "fcshc #{FCSHD::VERSION}"
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
89
|
+
parser.on("-h", "--help", "Show this message") do
|
90
|
+
puts parser
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
|
94
|
+
parser.separator ""
|
95
|
+
parser.separator "TL;DR: $ fcshc src/my_app.mxml"
|
50
96
|
end.parse!
|
51
97
|
|
98
|
+
$extra_arguments << "-debug" unless $production
|
99
|
+
|
52
100
|
for name in ARGV
|
53
101
|
if not File.exists? name
|
54
102
|
die "no such file or directory: #{name}"
|
55
103
|
elsif File.directory? name
|
56
|
-
$
|
104
|
+
$directories << File.expand_path(name)
|
57
105
|
elsif %w(.as .mxml).include? File.extname(name)
|
58
|
-
|
59
|
-
$source_filename = File.expand_path(name)
|
106
|
+
$source_files << File.expand_path(name)
|
60
107
|
elsif %w(.swc).include? File.extname(name)
|
61
|
-
$
|
108
|
+
$library_files << File.expand_path(name)
|
62
109
|
else
|
63
110
|
die "don't know what to do with file: #{name}"
|
64
111
|
end
|
65
112
|
end
|
66
113
|
|
67
|
-
|
68
|
-
die "missing source file to compile"
|
69
|
-
end
|
114
|
+
$compiling_swc = $output_file && $output_file.end_with?(".swc")
|
70
115
|
|
71
|
-
if $
|
72
|
-
$
|
73
|
-
|
116
|
+
if $compiling_swc
|
117
|
+
if [$source_files, $directories, $library_files] == [[], [], []]
|
118
|
+
die "must include at least one source file, directory, or SWC"
|
119
|
+
end
|
120
|
+
|
121
|
+
$fcshd_arguments = ["compc"]
|
122
|
+
|
123
|
+
for file in $source_files
|
124
|
+
$fcshd_arguments << "-include-sources+=#{file}"
|
125
|
+
end
|
126
|
+
|
127
|
+
for directory in $directories
|
128
|
+
$fcshd_arguments << "-include-sources+=#{directory}"
|
129
|
+
end
|
130
|
+
else
|
131
|
+
case $source_files.size
|
132
|
+
when 0: die "missing main application source file"
|
133
|
+
when 1: $source_file = $source_files.first
|
134
|
+
else die "multiple source files not allowed when compiling SWF"
|
135
|
+
end
|
136
|
+
|
137
|
+
if $directories.empty?
|
138
|
+
$directories << File.dirname($source_file)
|
139
|
+
end
|
74
140
|
|
75
|
-
if $
|
76
|
-
|
77
|
-
|
78
|
-
|
141
|
+
if $output_file == nil
|
142
|
+
$source_file.sub(/\.(as|mxml)$/, ".swf").tap do |x|
|
143
|
+
$output_file = File.expand_path(File.basename(x))
|
144
|
+
end
|
79
145
|
end
|
146
|
+
|
147
|
+
$fcshd_arguments = ["mxmlc", "#$source_file"]
|
80
148
|
end
|
81
149
|
|
82
|
-
$fcshd_arguments
|
150
|
+
$fcshd_arguments << "-output=#$output_file"
|
83
151
|
|
84
|
-
for directory in $
|
152
|
+
for directory in $directories
|
85
153
|
$fcshd_arguments << "-compiler.source-path+=#{directory}"
|
86
154
|
$fcshd_arguments << "-compiler.library-path+=#{directory}"
|
87
155
|
end
|
88
156
|
|
89
|
-
for
|
90
|
-
$fcshd_arguments << "-compiler.library-path+=#{
|
157
|
+
for file in $library_files
|
158
|
+
$fcshd_arguments << "-compiler.library-path+=#{file}"
|
91
159
|
end
|
92
160
|
|
93
161
|
$fcshd_arguments.concat($extra_arguments)
|
94
162
|
|
163
|
+
basedir = File.join(File.expand_path("."), "")
|
164
|
+
fcshd_command = $fcshd_arguments.join(" ")
|
165
|
+
|
166
|
+
if $verbose || $dry_run
|
167
|
+
warn fcshd_command.gsub(basedir, "")
|
168
|
+
end
|
169
|
+
|
170
|
+
exit if $dry_run
|
171
|
+
|
95
172
|
begin
|
96
173
|
host, port = "localhost", FCSHD::Server::PORT
|
97
174
|
socket = TCPSocket.new(host, port)
|
@@ -99,10 +176,6 @@ rescue Errno::ECONNREFUSED
|
|
99
176
|
die "could not connect to fcshd at #{host}:#{port}"
|
100
177
|
end
|
101
178
|
|
102
|
-
basedir = File.join(File.expand_path("."), "")
|
103
|
-
|
104
|
-
fcshd_command = $fcshd_arguments.join(" ")
|
105
|
-
warn fcshd_command.gsub(basedir, "") if $verbose
|
106
179
|
socket.puts fcshd_command
|
107
180
|
|
108
181
|
compiler_output = ""
|
@@ -115,7 +188,6 @@ socket.each_line do |line|
|
|
115
188
|
end
|
116
189
|
end
|
117
190
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
exit 1 if not output.succeeded?
|
191
|
+
transcript = FCSHD::Transcript[compiler_output]
|
192
|
+
STDOUT.write transcript.to_s(basedir)
|
193
|
+
exit 1 if not transcript.succeeded?
|
data/bin/fcshd
CHANGED
@@ -8,6 +8,11 @@ rescue LoadError
|
|
8
8
|
require "fcshd"
|
9
9
|
end
|
10
10
|
|
11
|
+
if ARGV == ["-v"] || ARGV == ["--version"]
|
12
|
+
puts "fcshd #{FCSHD::VERSION}"
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
|
11
16
|
logger = FCSHD::Logger.new(STDERR)
|
12
17
|
|
13
18
|
logger.die <<"^D" if not FCSHD::FlexHome.known?
|
@@ -26,6 +31,7 @@ begin
|
|
26
31
|
FCSHD::Server.new(FCSHD::Server::PORT, compiler, logger).run!
|
27
32
|
logger.log "Now listening to port #{FCSHD_PORT}."
|
28
33
|
rescue Interrupt
|
34
|
+
logger.log ""
|
29
35
|
logger.log "Exiting."
|
30
36
|
rescue Exception => error
|
31
37
|
logger.error "Could not listen to port #{FCSHD_PORT}: #{error}"
|
data/lib/fcshd/compiler.rb
CHANGED
data/lib/fcshd/problem.rb
CHANGED
@@ -1,153 +1,7 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
1
|
module FCSHD
|
4
|
-
class Problem < Struct.new(:
|
5
|
-
|
6
|
-
|
7
|
-
def mxmlc_message
|
8
|
-
raw_mxmlc_message.sub(ERROR_PREFIX, "")
|
9
|
-
end
|
10
|
-
|
11
|
-
def error?
|
12
|
-
raw_mxmlc_message =~ ERROR_PREFIX
|
13
|
-
end
|
14
|
-
|
15
|
-
def quote(string)
|
16
|
-
"‘#{string}’"
|
17
|
-
end
|
18
|
-
|
19
|
-
def message
|
20
|
-
case raw = raw_message
|
21
|
-
when String then raw
|
22
|
-
when Array then raw * "\n"
|
23
|
-
else fail
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def raw_message
|
28
|
-
case mxmlc_message
|
29
|
-
|
30
|
-
when "Unable to resolve MXML language version. Please specify the language namespace on the root document tag."
|
31
|
-
then
|
32
|
-
<<"^D"
|
33
|
-
missing MXML version
|
34
|
-
→ xmlns:fx="library://ns.adobe.com/mxml/2009"
|
35
|
-
→ xmlns="library://ns.adobe.com/flex/spark"
|
36
|
-
→ xmlns:mx="library://ns.adobe.com/flex/mx" (Flex 3 compatibility)
|
37
|
-
→ xmlns="http://www.adobe.com/2006/mxml" (Flex 3)
|
38
|
-
^D
|
39
|
-
|
40
|
-
when /^Incorrect number of arguments. Expected (\d+)\.$/
|
41
|
-
then "expected #$1 arguments"
|
42
|
-
|
43
|
-
when /^(?:Access of possibly undefined property|Call to a possibly undefined method) (.+) through a reference with static type (.+)\.$/
|
44
|
-
then "#{quote $1} undeclared in #$2"
|
45
|
-
|
46
|
-
when /^Attempted access of inaccessible property (.+) through a reference with static type (.+)\.$/
|
47
|
-
then "#{quote $1} inaccessible in #$2"
|
48
|
-
|
49
|
-
when
|
50
|
-
/^Could not resolve <(.+)> to a component implementation.$/,
|
51
|
-
/^Call to a possibly undefined method (.+).$/,
|
52
|
-
/^Access of undefined property (.+).$/,
|
53
|
-
/^The definition of base class (.+) was not found.$/,
|
54
|
-
/^Type was not found or was not a compile-time constant: (.+)\.$/
|
55
|
-
then
|
56
|
-
["#{quote $1} undeclared"].tap do |result|
|
57
|
-
FlexHome.find_component($1).tap do |package|
|
58
|
-
result << "→ import #{package}.*" if package
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
when /^Definition (.+) could not be found\.$/
|
63
|
-
then "#{quote $1} not found"
|
64
|
-
|
65
|
-
when
|
66
|
-
/^Implicit coercion of a value of type (.+) to an unrelated type (.+)\.$/,
|
67
|
-
|
68
|
-
/^Implicit coercion of a value with static type (.+) to a possibly unrelated type (.+)\./
|
69
|
-
|
70
|
-
then
|
71
|
-
actual, expected = $1, $2
|
72
|
-
expected_base = expected.sub(/.+:/, "")
|
73
|
-
actual_base = actual.sub(/.+:/, "")
|
74
|
-
if actual_base != expected_base
|
75
|
-
"expected #{expected_base} (got #{actual_base})"
|
76
|
-
else
|
77
|
-
"expected #{expected} (got #{actual})"
|
78
|
-
end
|
79
|
-
|
80
|
-
when "Method marked override must override another method."
|
81
|
-
then "overriding nonexistent method"
|
82
|
-
|
83
|
-
when "Overriding a function that is not marked for override."
|
84
|
-
then ["unmarked override", "→ add override keyword"]
|
85
|
-
|
86
|
-
when "Incompatible override."
|
87
|
-
then "incompatible override"
|
88
|
-
|
89
|
-
when /^Ambiguous reference to (.+)\.$/
|
90
|
-
then "#{quote $1} is ambiguous"
|
91
|
-
|
92
|
-
when /^A conflict exists with definition (.+) in namespace internal\.$/
|
93
|
-
then "#{quote $1} is conflicting"
|
94
|
-
|
95
|
-
when
|
96
|
-
/^Warning: parameter '(.+)' has no type declaration\.$/,
|
97
|
-
/^Warning: return value for function '(.+)' has no type declaration\.$/
|
98
|
-
then
|
99
|
-
case $1
|
100
|
-
when "anonymous" then "anonymous function"
|
101
|
-
else quote $1
|
102
|
-
end + " missing type declaration"
|
103
|
-
|
104
|
-
when /^A file found in a source-path must have the same package structure '(.*)', as the definition's package, '(.*)'\.$/
|
105
|
-
then "package should be #{quote $1}"
|
106
|
-
|
107
|
-
when /^Comparison between a value with static type (.+) and a possibly unrelated type (.+)\.$/
|
108
|
-
then "comparing #$1 to #$2"
|
109
|
-
|
110
|
-
when "Illegal assignment to a variable specified as constant."
|
111
|
-
then "modifying constant"
|
112
|
-
|
113
|
-
when "Function does not have a body."
|
114
|
-
then "missing function body"
|
115
|
-
|
116
|
-
when "Return type of a setter definition must be unspecified or void."
|
117
|
-
then "setter must return void"
|
118
|
-
|
119
|
-
when "Function does not return a value."
|
120
|
-
then "missing return statement"
|
121
|
-
|
122
|
-
when "Syntax error: expecting identifier before rightparen."
|
123
|
-
then "#{quote ")"} unexpected"
|
124
|
-
|
125
|
-
when
|
126
|
-
/^The (.+) attribute can only be used inside a package\./,
|
127
|
-
/^The (.+) attribute may be used only on class property definitions\./
|
128
|
-
then
|
129
|
-
"#{quote $1} unexpected"
|
130
|
-
|
131
|
-
else
|
132
|
-
mxmlc_message
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def formatted_message_lines
|
137
|
-
lines = message.lines.entries
|
138
|
-
if error?
|
139
|
-
first = <<"^D"
|
140
|
-
error: #{lines[0].chomp}
|
141
|
-
^D
|
142
|
-
rest = lines[1..-1].map do |line|
|
143
|
-
<<"^D"
|
144
|
-
#{line.chomp}
|
145
|
-
^D
|
146
|
-
end
|
147
|
-
[first] + rest
|
148
|
-
else
|
149
|
-
lines
|
150
|
-
end
|
2
|
+
class Problem < Struct.new(:location, :message)
|
3
|
+
def to_s(basedir)
|
4
|
+
"#{location.to_s(basedir)}: #{message}"
|
151
5
|
end
|
152
6
|
end
|
153
7
|
end
|
data/lib/fcshd/server.rb
CHANGED
@@ -21,10 +21,10 @@ module FCSHD
|
|
21
21
|
class Client < Struct.new(:socket, :compiler)
|
22
22
|
def run!
|
23
23
|
case command = socket.gets
|
24
|
-
when /^mxmlc /
|
24
|
+
when /^(mxmlc|compc) /
|
25
25
|
compiler.compile! command, socket
|
26
26
|
else
|
27
|
-
|
27
|
+
socket.puts "fcshd: unrecognized command: #{command}"
|
28
28
|
end
|
29
29
|
rescue Errno::EPIPE
|
30
30
|
logger.log "Broken pipe."
|
@@ -1,27 +1,15 @@
|
|
1
1
|
module FCSHD
|
2
|
-
class SourceLocation < Struct.new
|
3
|
-
|
4
|
-
|
5
|
-
def to_s
|
6
|
-
relative_filename.tap do |result|
|
7
|
-
result << ":#{line_number}" if line_number
|
8
|
-
end
|
2
|
+
class SourceLocation < Struct.new(:filename, :line_number)
|
3
|
+
def to_s(basedir=nil)
|
4
|
+
"#{relative_filename(basedir)}:#{line_number || 0}"
|
9
5
|
end
|
10
6
|
|
11
|
-
def relative_filename
|
7
|
+
def relative_filename(basedir)
|
12
8
|
if basedir
|
13
9
|
filename.sub(/^#{Regexp.quote(basedir)}/, "")
|
14
10
|
else
|
15
11
|
filename
|
16
12
|
end
|
17
13
|
end
|
18
|
-
|
19
|
-
def with_basedir(new_basedir)
|
20
|
-
dup.tap { |result| result.basedir = new_basedir }
|
21
|
-
end
|
22
|
-
|
23
|
-
def without_column_number
|
24
|
-
dup.tap { |result| result.column_number = nil }
|
25
|
-
end
|
26
14
|
end
|
27
15
|
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module FCSHD
|
4
|
+
class Transcript; end
|
5
|
+
class Transcript::Item < Struct.new(:location, :mxmlc_message)
|
6
|
+
def to_s(basedir)
|
7
|
+
problems.map { |problem| problem.to_s(basedir) }.join("\n")
|
8
|
+
end
|
9
|
+
|
10
|
+
def problems
|
11
|
+
get_problems(parsed_message)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def get_problems(item)
|
17
|
+
case item
|
18
|
+
when String
|
19
|
+
get_problems_at(location, item)
|
20
|
+
when Array
|
21
|
+
if item.first.is_a? SourceLocation
|
22
|
+
get_problems_at(item[0], item[1])
|
23
|
+
else
|
24
|
+
item.map { |item| get_problems(item) }.flatten(1)
|
25
|
+
end
|
26
|
+
else fail
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_problems_at(location, message)
|
31
|
+
message.split("\n").map do |message|
|
32
|
+
Problem[location, message]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parsed_message
|
37
|
+
case FCSHD.trim(mxmlc_message).sub(/^Error: /, "")
|
38
|
+
when "Unable to resolve MXML language version. Please specify the language namespace on the root document tag.": <<EOF
|
39
|
+
error: missing MXML version
|
40
|
+
error: hint: xmlns:fx="library://ns.adobe.com/mxml/2009"
|
41
|
+
error: hint: xmlns="library://ns.adobe.com/flex/spark"
|
42
|
+
error: hint: xmlns:mx="library://ns.adobe.com/flex/mx" (Flex 4)
|
43
|
+
error: hint: xmlns="http://www.adobe.com/2006/mxml" (Flex 3)
|
44
|
+
EOF
|
45
|
+
when /^Incorrect number of arguments. Expected (\d+)\.$/: <<EOF
|
46
|
+
error: expected #$1 arguments
|
47
|
+
EOF
|
48
|
+
when
|
49
|
+
/^Access of possibly undefined property (.+) through a reference with static type (.+)\.$/,
|
50
|
+
/^Call to a possibly undefined method (.+) through a reference with static type (.+)\.$/,
|
51
|
+
/^Cannot resolve attribute '(.+)' for component type (.+)\.$/
|
52
|
+
then <<EOF
|
53
|
+
error: #{quote $1} undeclared in #{name $2}
|
54
|
+
EOF
|
55
|
+
when /^Attempted access of inaccessible property (.+) through a reference with static type (.+)\.$/: <<EOF
|
56
|
+
error: #{quote $1} inaccessible in #{name $2}
|
57
|
+
EOF
|
58
|
+
when
|
59
|
+
/^Could not resolve <(.+)> to a component implementation\.$/,
|
60
|
+
/^Call to a possibly undefined method (.+)\.$/,
|
61
|
+
/^Access of undefined property (.+)\.$/,
|
62
|
+
/^The definition of base class (.+) was not found\.$/,
|
63
|
+
/^Type was not found or was not a compile-time constant: (.+)\.$/
|
64
|
+
then
|
65
|
+
[<<EOF].tap do |result|
|
66
|
+
error: #{quote $1} undeclared
|
67
|
+
EOF
|
68
|
+
FlexHome.find_component($1).tap do |package|
|
69
|
+
result << <<EOF if package
|
70
|
+
error: hint: import #{package}.#$1
|
71
|
+
EOF
|
72
|
+
end
|
73
|
+
end
|
74
|
+
when /^Definition (.+) could not be found\.$/: <<EOF
|
75
|
+
error: #{quote $1} not found
|
76
|
+
EOF
|
77
|
+
when /^Implicit coercion of a value of type (.+) to an unrelated type (.+)\.$/, /^Implicit coercion of a value with static type (.+) to a possibly unrelated type (.+)\./
|
78
|
+
actual, expected = $1, $2
|
79
|
+
expected_local = expected.sub(/.+:/, "")
|
80
|
+
actual_local = actual.sub(/.+:/, "")
|
81
|
+
actual_local != expected_local ? <<EOF : <<EOF
|
82
|
+
error: expected #{expected_local} (got #{actual_local})
|
83
|
+
EOF
|
84
|
+
error: expected #{expected} (got #{actual})
|
85
|
+
EOF
|
86
|
+
when "Method marked override must override another method.": <<EOF
|
87
|
+
error: overriding nonexistent method
|
88
|
+
EOF
|
89
|
+
when "Overriding a function that is not marked for override.": <<EOF
|
90
|
+
error: unmarked override
|
91
|
+
EOF
|
92
|
+
when "Incompatible override.": <<EOF
|
93
|
+
error: incompatible override
|
94
|
+
EOF
|
95
|
+
when /^Ambiguous reference to (.+)\.$/: <<EOF
|
96
|
+
error: #{quote $1} is ambiguous
|
97
|
+
EOF
|
98
|
+
when /^Can not resolve a multiname reference unambiguously. (\S+) \(from ([^)]+)\) and (\S+) \(from ([^)]+)\) are available\.$/
|
99
|
+
then
|
100
|
+
[<<EOF, [SourceLocation[$2], <<EOF], [SourceLocation[$4], <<EOF]]
|
101
|
+
error: #{quote name $1} conflicts with #{quote name $3}
|
102
|
+
EOF
|
103
|
+
error: conflicting definition
|
104
|
+
EOF
|
105
|
+
error: conflicting definition
|
106
|
+
EOF
|
107
|
+
when /^A conflict exists with definition (.+) in namespace internal\.$/: <<EOF
|
108
|
+
error: #{quote $1} conflicts with an internal name
|
109
|
+
EOF
|
110
|
+
when
|
111
|
+
/^Warning: parameter '(.+)' has no type declaration\.$/,
|
112
|
+
/^Warning: return value for function '(.+)' has no type declaration\.$/
|
113
|
+
then
|
114
|
+
who = $1 == "anonymous" ? "anonymous function" : quote($1)
|
115
|
+
<<EOF
|
116
|
+
error: #{who} missing type declaration
|
117
|
+
EOF
|
118
|
+
when /^A file found in a source-path must have the same package structure '(.*)', as the definition's package, '(.*)'\.$/: <<EOF
|
119
|
+
error: package should be #{quote $1}
|
120
|
+
EOF
|
121
|
+
when /^Comparison between a value with static type (.+) and a possibly unrelated type (.+)\.$/: <<EOF
|
122
|
+
error: comparing #$1 to #$2
|
123
|
+
EOF
|
124
|
+
when "Illegal assignment to a variable specified as constant.": <<EOF
|
125
|
+
error: modifying constant
|
126
|
+
EOF
|
127
|
+
when "Function does not have a body.": <<EOF
|
128
|
+
error: missing function body"
|
129
|
+
EOF
|
130
|
+
when "Return type of a setter definition must be unspecified or void.": <<EOF
|
131
|
+
error: setter must return void"
|
132
|
+
EOF
|
133
|
+
when "Function does not return a value.": <<EOF
|
134
|
+
error: missing return statement"
|
135
|
+
EOF
|
136
|
+
when "Syntax error: expecting identifier before rightparen.": <<EOF
|
137
|
+
error: #{quote ")"} unexpected"
|
138
|
+
EOF
|
139
|
+
when
|
140
|
+
/^The (.+) attribute can only be used inside a package\./,
|
141
|
+
/^The (.+) attribute may be used only on class property definitions\./
|
142
|
+
then
|
143
|
+
<<EOF
|
144
|
+
error: #{quote $1} unexpected
|
145
|
+
EOF
|
146
|
+
else
|
147
|
+
mxmlc_message
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def quote(string) "‘#{string}’" end
|
152
|
+
def name(string) string.sub! ":", "." end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module FCSHD
|
2
|
+
class Transcript; end
|
3
|
+
class Transcript::Parser < Struct.new(:lines)
|
4
|
+
def parse!
|
5
|
+
Transcript.new.tap do |result|
|
6
|
+
@result = result
|
7
|
+
parse_line! until lines.empty?
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :result
|
12
|
+
|
13
|
+
def parse_line!
|
14
|
+
take_line! do |line|
|
15
|
+
case FCSHD.trim(line)
|
16
|
+
when / \((\d+) bytes\)$/
|
17
|
+
result.succeeded = true
|
18
|
+
|
19
|
+
when "Nothing has changed since the last compile. Skip..."
|
20
|
+
result.n_compiled_files = 0
|
21
|
+
|
22
|
+
when /^Files changed: (\d+) Files affected: (\d+)$/
|
23
|
+
result.n_compiled_files = $1.to_i + $2.to_i
|
24
|
+
|
25
|
+
when /^(\/.+?)(?:\((\d+)\))?: (?:col: \d+ )?(.+)$/
|
26
|
+
result << Transcript::Item[SourceLocation[$1, $2.to_i], $3]
|
27
|
+
skip_indented_lines! # Ignore the "diagram" of the problem.
|
28
|
+
|
29
|
+
when /^Required RSLs:$/
|
30
|
+
skip_indented_lines! # Does anybody care about this?
|
31
|
+
|
32
|
+
when /^(Recompile|Reason): /
|
33
|
+
when /^Loading configuration file /
|
34
|
+
|
35
|
+
else
|
36
|
+
# Let unrecognized lines pass through verbatim.
|
37
|
+
if line.start_with? "fcshd: "
|
38
|
+
result << line
|
39
|
+
else
|
40
|
+
# XXX: What about when we support compc?
|
41
|
+
result << "mxmlc: #{line}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def take_line!
|
48
|
+
yield skip_line!
|
49
|
+
end
|
50
|
+
|
51
|
+
def skip_line!
|
52
|
+
current_line
|
53
|
+
ensure
|
54
|
+
lines.shift
|
55
|
+
end
|
56
|
+
|
57
|
+
def current_line
|
58
|
+
lines.first.chomp
|
59
|
+
end
|
60
|
+
|
61
|
+
def skip_indented_lines!
|
62
|
+
skip_line! until lines.empty? or current_line =~ /^\S/
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module FCSHD
|
2
|
+
class Transcript
|
3
|
+
def self.[] text
|
4
|
+
Parser.new(text.split("\n")).parse!
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@items = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def << item
|
12
|
+
@items << item
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :n_compiled_files
|
16
|
+
|
17
|
+
def succeeded= value; @succeeded = value; end
|
18
|
+
def succeeded?; @succeeded; end
|
19
|
+
|
20
|
+
def to_s(basedir)
|
21
|
+
@items.map do |item|
|
22
|
+
case item
|
23
|
+
when Item
|
24
|
+
item.to_s(basedir)
|
25
|
+
else
|
26
|
+
item.to_s
|
27
|
+
end
|
28
|
+
end.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def nothing_to_do?
|
32
|
+
n_compiled_files == 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/fcshd/version.rb
CHANGED
data/lib/fcshd.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
|
+
module FCSHD
|
2
|
+
def self.trim(string)
|
3
|
+
string.gsub(/\s+/, " ").gsub(/^ | $/, "")
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
require "fcshd/compiler"
|
2
|
-
require "fcshd/compiler-output"
|
3
|
-
require "fcshd/compiler-output-writer"
|
4
8
|
require "fcshd/flex-home"
|
5
9
|
require "fcshd/logger"
|
6
10
|
require "fcshd/problem"
|
7
11
|
require "fcshd/server"
|
8
12
|
require "fcshd/source-location"
|
13
|
+
require "fcshd/transcript"
|
14
|
+
require "fcshd/transcript-item"
|
15
|
+
require "fcshd/transcript-parser"
|
9
16
|
require "fcshd/version"
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fcshd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.3.1
|
8
|
+
- 5
|
9
|
+
version: "0.5"
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Daniel Brockman
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-
|
17
|
+
date: 2011-12-01 00:00:00 Z
|
19
18
|
dependencies: []
|
20
19
|
|
21
20
|
description: |
|
@@ -42,14 +41,15 @@ files:
|
|
42
41
|
- bin/fcshd
|
43
42
|
- fcshd.gemspec
|
44
43
|
- lib/fcshd.rb
|
45
|
-
- lib/fcshd/compiler-output-writer.rb
|
46
|
-
- lib/fcshd/compiler-output.rb
|
47
44
|
- lib/fcshd/compiler.rb
|
48
45
|
- lib/fcshd/flex-home.rb
|
49
46
|
- lib/fcshd/logger.rb
|
50
47
|
- lib/fcshd/problem.rb
|
51
48
|
- lib/fcshd/server.rb
|
52
49
|
- lib/fcshd/source-location.rb
|
50
|
+
- lib/fcshd/transcript-item.rb
|
51
|
+
- lib/fcshd/transcript-parser.rb
|
52
|
+
- lib/fcshd/transcript.rb
|
53
53
|
- lib/fcshd/version.rb
|
54
54
|
homepage: http://github.com/dbrock/fcshd
|
55
55
|
licenses: []
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
requirements: []
|
81
81
|
|
82
82
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.8.
|
83
|
+
rubygems_version: 1.8.11
|
84
84
|
signing_key:
|
85
85
|
specification_version: 3
|
86
86
|
summary: Usable CLI for the Adobe Flex compiler shell (fcsh)
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module FCSHD
|
2
|
-
class CompilerOutputWriter
|
3
|
-
def initialize(output, basedir)
|
4
|
-
@output = output
|
5
|
-
@basedir = basedir
|
6
|
-
end
|
7
|
-
|
8
|
-
def write_uninterpreted_line! line
|
9
|
-
@output.puts line
|
10
|
-
end
|
11
|
-
|
12
|
-
def write_problem! problem
|
13
|
-
location = problem.source_location.with_basedir(@basedir)
|
14
|
-
for line in problem.formatted_message_lines do
|
15
|
-
@output.puts "#{location}: #{line}"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
module FCSHD
|
2
|
-
class CompilerOutput
|
3
|
-
def self.[] text, basedir
|
4
|
-
new.tap do |result|
|
5
|
-
Parser.new(text.lines.entries, basedir, result).parse!
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_accessor :n_compiled_files
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@events = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def << event
|
16
|
-
@events << event
|
17
|
-
end
|
18
|
-
|
19
|
-
def write! writer
|
20
|
-
for event in @events
|
21
|
-
case event
|
22
|
-
when String
|
23
|
-
writer.write_uninterpreted_line! event
|
24
|
-
when Problem
|
25
|
-
writer.write_problem! event
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def nothing_to_do?
|
31
|
-
n_compiled_files == 0
|
32
|
-
end
|
33
|
-
|
34
|
-
def succeeded!
|
35
|
-
@succeeded = true
|
36
|
-
end
|
37
|
-
|
38
|
-
def succeeded?
|
39
|
-
@succeeded
|
40
|
-
end
|
41
|
-
|
42
|
-
class Parser < Struct.new(:lines, :basedir, :result)
|
43
|
-
def parse!
|
44
|
-
parse_line! until lines.empty?
|
45
|
-
end
|
46
|
-
|
47
|
-
def parse_line!
|
48
|
-
take_line! do |line|
|
49
|
-
case line
|
50
|
-
when /^(Recompile|Reason): /
|
51
|
-
when /^Loading configuration file /
|
52
|
-
when /^(.+\.swf) \((\d+) bytes\)$/
|
53
|
-
result.succeeded!
|
54
|
-
when "Nothing has changed since the last compile. Skip..."
|
55
|
-
result.n_compiled_files = 0
|
56
|
-
when /^Files changed: (\d+) Files affected: (\d+)$/
|
57
|
-
result.n_compiled_files = $1.to_i + $2.to_i
|
58
|
-
when /^(\/.+?)(?:\((\d+)\))?: (?:col: (\d+) )?(.+)$/
|
59
|
-
location = SourceLocation[$1, $2.to_i, $3.to_i, basedir]
|
60
|
-
result << Problem[location, $4]
|
61
|
-
skip_indented_lines!
|
62
|
-
when /^Required RSLs:$/
|
63
|
-
skip_indented_lines!
|
64
|
-
when /^fcshd: /
|
65
|
-
result << line
|
66
|
-
else
|
67
|
-
result << "mxmlc: #{line}"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def take_line!
|
73
|
-
yield skip_line!
|
74
|
-
end
|
75
|
-
|
76
|
-
def skip_line!
|
77
|
-
current_line
|
78
|
-
ensure
|
79
|
-
lines.shift
|
80
|
-
end
|
81
|
-
|
82
|
-
def current_line
|
83
|
-
lines[0].chomp
|
84
|
-
end
|
85
|
-
|
86
|
-
def skip_indented_lines!
|
87
|
-
skip_line! until lines.empty? or current_line =~ /^\S/
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|