fcshd 0.3.1 → 0.5
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.
- 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
|