Skip to content

Commit 16eb3bf

Browse files
committed
src: workspace
1 parent a11bab4 commit 16eb3bf

File tree

1 file changed

+151
-84
lines changed

1 file changed

+151
-84
lines changed

src/workspace.cr

Lines changed: 151 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -18,110 +18,177 @@
1818
# -----------------------------------------------------------------------
1919

2020
module MoonScript
21-
class Workspace
22-
getter result: TypeChecker | Error = Error.new(:uninitialized_workspace)
23-
24-
@cache: Hash(String, Ast | Error) = {} of String => Ast | Error
21+
class Workspace
22+
getter result : TypeChecker | Error = Error.new(:unitialized_workspace)
23+
24+
@cache : Hash(String, Ast | Error) = {} of String => Ast | Error
25+
@listener : Proc(TypeChecker | Error, Nil) | Nil
26+
27+
def initialize(
28+
*,
29+
@listener : Proc(TypeChecker | Error, Nil) | Nil,
30+
@include_tests : Bool,
31+
dot_env : String,
32+
@format : Bool,
33+
@check : Check,
34+
@path : String,
35+
)
36+
@dot_env =
37+
File.basename(dot_env)
38+
39+
(@watcher = Watcher.new(&->update(Array(String), Symbol)))
40+
.tap { reset }
41+
.watch
42+
end
2543

26-
@listener: Proc(TypeChecker | Error, Nil) | Nil
44+
def update(contents : String, path : String) : Nil
45+
@cache[path] = Parser.parse?(contents, path)
46+
end
2747

28-
def initialize(*, @listener: Proc(TypeChecker | Error, Nil) | Nil, @include_tests: Bool, dot_env: String, @format: Bool, @check: Check, @path: String )
29-
@dot_env = File.basename(dot_env)
48+
def delete(path : String) : Nil
49+
@cache.delete(path)
50+
end
3051

31-
(@watcher = Watcher.new(&->update(Array(String), Symbol)))
32-
.tap { reset }
33-
.watch
34-
end
52+
def artifacts : TypeChecker::Artifacts | Error
53+
map_error(result, &.artifacts)
54+
end
3555

36-
def update(contents: String, path: String) : Nil
37-
@cache[path] = Parser.parse?(contents, path)
38-
end
56+
def ast(path : String) : Ast | Error | Nil
57+
@cache[path]?
58+
end
3959

40-
def delete(path: String) : Nil
41-
@cache.delete(path)
42-
end
60+
def ast : Ast | Error
61+
map_error(artifacts, &.ast)
62+
end
4363

44-
def artifacts : TypeChecker::Artifacts | Error
45-
map_error(result, &.artifacts)
64+
def unchecked_ast
65+
@cache
66+
.values
67+
.select(Ast)
68+
.reduce(Ast.new) { |memo, item| memo.merge item }
69+
.tap do |item|
70+
unless item.type_definitions.index(&.name.==("Maybe"))
71+
item.merge(Core.ast)
72+
end
4673
end
74+
.normalize
75+
end
4776

48-
def ast(path: String) : Ast | Error | Nil
49-
@cache[path]?
50-
end
77+
def nodes_at_cursor(
78+
*,
79+
column : Int64,
80+
path : String,
81+
line : Int64,
82+
) : Array(Ast::Node) | Error
83+
map_error(ast, &.nodes_at_cursor(
84+
line: line, column: column, path: path))
85+
end
5186

52-
def ast: Ast | Error
53-
map_error(artifacts, &.ast)
54-
end
87+
def nodes_at_path(path : String)
88+
map_error(ast, &.nodes_at_path(path))
89+
end
5590

56-
def nodes_at_path(path: String)
57-
map_error(ast, &.nodes_at_path(path))
58-
end
91+
def formatter_config
92+
MoonJson.parse?(@path, search: true).try(&.formatter) ||
93+
Formatter::Config.new
94+
end
5995

60-
def formatter_config
61-
MoonJson.parse?(@path, search: true).try(&.formatter) || Formatter::Config.new
62-
end
96+
def format(node : Ast::Node | Nil) : String | Nil
97+
Formatter.new(formatter_config).format!(node)
98+
end
6399

64-
def format(node: Ast::Node | Nil) : String | Nil
65-
Formatter.new(formatter_config).format!(node)
66-
end
100+
def format(path : String) : String | Error | Nil
101+
case item = ast(path)
102+
in Ast
103+
Formatter.new(formatter_config).format(item)
104+
in Error, Nil
105+
item
106+
end
107+
end
67108

68-
def format(path: String) : String | Error | Nil
69-
case item = ast(path)
70-
in Ast
71-
Formatter.new(formatter_config).format(item)
72-
in Error, Nil
73-
item
74-
end
75-
end
109+
def reset
110+
@cache.clear
111+
@watcher.patterns =
112+
SourceFiles.everything(
113+
MoonJson.parse(@path, search: true),
114+
include_tests: @include_tests,
115+
dot_env: @dot_env)
116+
rescue error : Error
117+
set(error)
118+
end
76119

77-
def reset
78-
@cache.clear
79-
@watcher.patterns = SourceFiles.everything(MoonJson.parse(@path, search: true), include_tests: @include_tests, dot_env: @dot_env)
80-
rescue error: Error
81-
set(error)
120+
def check
121+
Logger.log "Type Checking" do
122+
if error = @cache.values.select(Error).first?
123+
error
124+
else
125+
TypeChecker.new(
126+
check_everything: @check.unreachable?,
127+
check_env: @check.environment?,
128+
ast: unchecked_ast
129+
).tap(&.check)
82130
end
131+
end
132+
rescue error : Error
133+
error
134+
end
83135

84-
def check
85-
Logger.log "Type checking" do
86-
if error = @cache.values.select(Error).first?
87-
error
88-
else
89-
TypeChecker.new(check_everything: @check.unreachable?, check_env: @check.environment, ast: unchecked_ast).tap(&check)
136+
def update(files : Array(String), reason : Symbol)
137+
actions = [] of Symbol
138+
139+
Logger.log "Parsing files" do
140+
files.each do |file|
141+
if File.extname(file) == ".moon"
142+
if File.exists?(file)
143+
contents = File.read(file)
144+
update(contents, file)
145+
146+
if @format
147+
case ast = ast(file)
148+
when Ast
149+
formatted =
150+
Formatter.new(formatter_config).format(ast) + "\n"
151+
152+
if formatted != contents
153+
File.write(file, formatted)
154+
end
90155
end
91-
rescue error: Error
92-
error
156+
end
157+
else
158+
delete(file)
93159
end
94-
end
95160

96-
def update(files: Array(String), reason: Symbol)
97-
actions = [] of Symbol
98-
99-
Logger.log "Parsing files" do
100-
files.each do |file|
101-
if File.extname(file) == ".moon"
102-
if File.exists?(file)
103-
contents = File.read(file)
104-
update(contents, file)
105-
106-
if @format
107-
case ast = ast(file)
108-
when Ast formatted = Formatter.new(formatter_config).format(ast) + "\n"
109-
110-
end
161+
actions << :compile
162+
else
163+
case File.basename(file)
164+
when @dot_env
165+
Env.init(file)
166+
end
111167

112-
private def set(value: TypeChecker | Error) : Nil
113-
@result = value
114-
@listener.try(&.call(value))
168+
actions << :reset
169+
end
115170
end
171+
end
116172

117-
private def map_error(item: T | Error, & : T -> R) : R | Error forall T, R
118-
case item
119-
in Error
120-
item
121-
in T
122-
yield item
123-
end
124-
end
125-
173+
if actions.includes?(:reset) && reason == :modified
174+
reset
175+
elsif actions.includes?(:compile)
176+
set(check)
177+
end
178+
end
179+
180+
private def set(value : TypeChecker | Error) : Nil
181+
@result = value
182+
@listener.try(&.call(value))
183+
end
184+
185+
private def map_error(item : T | Error, & : T -> R) : R | Error forall T, R
186+
case item
187+
in Error
188+
item
189+
in T
190+
yield item
191+
end
126192
end
127-
end
193+
end
194+
end

0 commit comments

Comments
 (0)