Skip to content
This repository was archived by the owner on Nov 5, 2024. It is now read-only.

Commit 1a2e999

Browse files
committed
emit precise information about diagnostics
1 parent d15f2d4 commit 1a2e999

File tree

15 files changed

+509
-204
lines changed

15 files changed

+509
-204
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ build-convert/target
55
build-convert/Cargo.lock
66
src/node.h
77
src/node.cc
8+
src/message.h
9+
src/message.cc
810

911
lib-ruby-parser.a
1012
src/lib-ruby-parser.h

binding.gyp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"src/magic_comment.cc",
1414
"src/node.cc",
1515
"src/parser_result.cc",
16+
"src/message.cc",
17+
"src/convert/size_t.cc",
18+
"src/convert/string.cc",
1619
],
1720
"include_dirs": [
1821
"<!@(node -p \"require('node-addon-api').include\")",

build-convert/build.rs

Lines changed: 10 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,192 +1,19 @@
11
extern crate lib_ruby_parser_nodes;
22

3-
use lib_ruby_parser_nodes::{Field, Node};
4-
5-
fn build_comparison(node: &Node) -> String {
6-
format!(
7-
"if constexpr (std::is_same_v<T, std::unique_ptr<lib_ruby_parser::{class_name}>>) {{
8-
return convert(std::move(inner), env);
9-
}}",
10-
class_name = node.struct_name
11-
)
12-
}
13-
14-
fn field_name(f: &Field) -> String {
15-
match &f.field_name[..] {
16-
"default" => "default_",
17-
"operator" => "operator_",
18-
other => other,
19-
}
20-
.to_owned()
21-
}
22-
23-
fn build_converter(node: &Node) -> String {
24-
let fields: Vec<String> = node
25-
.fields
26-
.iter()
27-
.map(|f| {
28-
format!(
29-
"convert(std::move(node->{name}), env),",
30-
name = field_name(f)
31-
)
32-
})
33-
.collect();
34-
35-
format!(
36-
"Napi::Value convert(std::unique_ptr<lib_ruby_parser::{class_name}> node, Napi::Env env) {{
37-
if (!node) {{
38-
return env.Null();
39-
}}
40-
return {class_name}Ctor.New({{
41-
{fields}
42-
}});
43-
}}",
44-
class_name = node.struct_name,
45-
fields = fields.join("\n ")
46-
)
47-
}
48-
49-
fn ctor_definition(node: &Node) -> String {
50-
format!("Napi::FunctionReference {}Ctor;", node.struct_name)
51-
}
52-
53-
fn ctor_fn_definition(node: &Node) -> String {
54-
let set_fields: Vec<String> = node
55-
.fields
56-
.iter()
57-
.enumerate()
58-
.map(|(idx, f)| {
59-
format!(
60-
"self.Set(\"{name}\", info[{idx}]);",
61-
name = field_name(f),
62-
idx = idx
63-
)
64-
})
65-
.collect();
66-
67-
format!(
68-
"Napi::Value {name}CtorFn(const Napi::CallbackInfo &info)
69-
{{
70-
Napi::Object self = info.This().As<Napi::Object>();
71-
Napi::Env env = info.Env();
72-
{set_fields}
73-
return env.Null();
74-
}}
75-
",
76-
name = node.struct_name,
77-
set_fields = set_fields.join("\n ")
78-
)
79-
}
80-
81-
fn init_exports(node: &Node) -> String {
82-
format!(
83-
"fn = Napi::Function::New(env, {name}CtorFn, \"{name}\");
84-
{name}Ctor = Napi::Persistent(fn);
85-
{name}Ctor.SuppressDestruct();
86-
exports.Set(\"{name}\", fn);
87-
",
88-
name = node.struct_name
89-
)
90-
}
3+
mod gen;
914

925
fn main() {
936
let nodes = lib_ruby_parser_nodes::nodes();
947

95-
let ctor_definitions: Vec<String> = nodes.iter().map(ctor_definition).collect();
96-
let ctor_fn_definitions: Vec<String> = nodes.iter().map(ctor_fn_definition).collect();
97-
98-
let converters: Vec<String> = nodes.iter().map(build_converter).collect();
99-
let comparisons: Vec<String> = nodes.iter().map(build_comparison).collect();
100-
let init_exports: Vec<String> = nodes.iter().map(init_exports).collect();
101-
102-
let node_h = format!(
103-
"#ifndef LIB_RUBY_PARSER_NODE_NODE_H
104-
#define LIB_RUBY_PARSER_NODE_NODE_H
8+
gen::NodeH::new(&nodes).write();
9+
gen::NodeCc::new(&nodes).write();
10510

106-
#include <napi.h>
107-
#include \"lib-ruby-parser.h\"
108-
109-
namespace lib_ruby_parser_node
110-
{{
111-
112-
Napi::Value convert(std::unique_ptr<lib_ruby_parser::Node> node, Napi::Env env);
113-
void InitNodeTypes(Napi::Env env, Napi::Object exports);
114-
115-
}} // namespace lib_ruby_parser_node
116-
117-
#endif // LIB_RUBY_PARSER_NODE_NODE_H
118-
"
119-
);
120-
121-
let node_cc = format!(
122-
"#include \"node.h\"
123-
#include \"loc.h\"
124-
#include \"bytes.h\"
125-
126-
namespace lib_ruby_parser_node
127-
{{
128-
{ctor_definitions}
129-
130-
{ctor_fn_definitions}
131-
132-
Napi::Value convert(std::unique_ptr<lib_ruby_parser::Node> node, Napi::Env env);
133-
Napi::Value convert(lib_ruby_parser::Node node, Napi::Env env);
134-
135-
Napi::Value convert(std::string s, Napi::Env env)
136-
{{
137-
return Napi::String::New(env, s);
138-
}}
139-
140-
Napi::Value convert(size_t n, Napi::Env env)
141-
{{
142-
return Napi::Number::New(env, 0);
143-
}}
144-
145-
Napi::Value convert(std::vector<lib_ruby_parser::Node> nodes, Napi::Env env)
146-
{{
147-
Napi::Array arr = Napi::Array::New(env, nodes.size());
148-
for (size_t i = 0; i < nodes.size(); i++)
149-
{{
150-
arr.Set(i, convert(std::move(nodes[i]), env));
151-
}}
152-
return arr;
153-
}}
154-
155-
{converters}
156-
157-
Napi::Value convert(std::unique_ptr<lib_ruby_parser::Node> node, Napi::Env env)
158-
{{
159-
if (!node) {{
160-
return env.Null();
161-
}}
162-
return std::visit([env](auto &&inner) -> Napi::Value {{
163-
using T = std::decay_t<decltype(inner)>;
164-
{comparisons}
165-
}}, node->inner);
166-
}}
167-
168-
Napi::Value convert(lib_ruby_parser::Node node, Napi::Env env)
169-
{{
170-
return std::visit([env](auto &&inner) {{
171-
using T = std::decay_t<decltype(inner)>;
172-
{comparisons}
173-
}}, node.inner);
174-
}}
175-
176-
void InitNodeTypes(Napi::Env env, Napi::Object exports) {{
177-
Napi::Function fn;
178-
179-
{init_exports}
180-
}}
181-
}} // namespace lib_ruby_parser_node
182-
",
183-
converters = converters.join("\n "),
184-
comparisons = comparisons.join("\n "),
185-
ctor_definitions = ctor_definitions.join("\n "),
186-
ctor_fn_definitions = ctor_fn_definitions.join("\n "),
187-
init_exports = init_exports.join("\n ")
188-
);
11+
let messages = lib_ruby_parser_nodes::messages()
12+
.sections
13+
.iter()
14+
.flat_map(|s| s.messages.to_owned())
15+
.collect::<Vec<_>>();
18916

190-
std::fs::write("../src/node.h", &node_h).unwrap();
191-
std::fs::write("../src/node.cc", &node_cc).unwrap();
17+
gen::MessageH::new(&messages).write();
18+
gen::MessageCc::new(&messages).write();
19219
}

build-convert/gen/message_cc.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use lib_ruby_parser_nodes::MessageField;
2+
3+
pub(crate) struct MessageCc<'a> {
4+
messages: &'a [lib_ruby_parser_nodes::Message],
5+
}
6+
7+
impl<'a> MessageCc<'a> {
8+
pub(crate) fn new(messages: &'a [lib_ruby_parser_nodes::Message]) -> Self {
9+
Self { messages }
10+
}
11+
12+
pub(crate) fn write(&self) {
13+
std::fs::write("../src/message.cc", self.contents()).unwrap();
14+
}
15+
16+
fn contents(&self) -> String {
17+
format!(
18+
"#include \"message.h\"
19+
#include \"convert/string.h\"
20+
#include \"convert/size_t.h\"
21+
22+
namespace lib_ruby_parser_node {{
23+
{ctor_declarations}
24+
25+
{ctor_fn_definitions}
26+
27+
{converters}
28+
29+
Napi::Value convert(std::unique_ptr<lib_ruby_parser::DiagnosticMessage> diagnostic_message, Napi::Env env)
30+
{{
31+
if (!diagnostic_message) {{
32+
return env.Null();
33+
}}
34+
return std::visit([env](auto &&variant) -> Napi::Value {{
35+
using T = std::decay_t<decltype(variant)>;
36+
{comparisons}
37+
}}, diagnostic_message->variant);
38+
}}
39+
40+
void InitMessageTypes(Napi::Env env, Napi::Object exports) {{
41+
Napi::Function fn;
42+
43+
{init_exports}
44+
}}
45+
}}
46+
47+
",
48+
ctor_declarations = self.ctor_declarations().join("\n "),
49+
ctor_fn_definitions = self.ctor_fn_definitions().join("\n "),
50+
converters = self.converters().join("\n "),
51+
comparisons = self.comparisons().join("\n "),
52+
init_exports = self.init_exports().join("\n ")
53+
)
54+
}
55+
56+
fn ctor_declarations(&self) -> Vec<String> {
57+
self.messages.iter().map(ctor_declaration).collect()
58+
}
59+
fn ctor_fn_definitions(&self) -> Vec<String> {
60+
self.messages.iter().map(ctor_fn_definition).collect()
61+
}
62+
fn converters(&self) -> Vec<String> {
63+
self.messages.iter().map(converter).collect()
64+
}
65+
fn comparisons(&self) -> Vec<String> {
66+
self.messages.iter().map(comparison).collect()
67+
}
68+
fn init_exports(&self) -> Vec<String> {
69+
self.messages.iter().map(init_exports).collect()
70+
}
71+
}
72+
73+
fn ctor_declaration(message: &lib_ruby_parser_nodes::Message) -> String {
74+
format!("Napi::FunctionReference {}Ctor;", message.name)
75+
}
76+
77+
fn field_name(f: &lib_ruby_parser_nodes::MessageField) -> String {
78+
match &f.name[..] {
79+
"default" => "default_",
80+
"operator" => "operator_",
81+
other => other,
82+
}
83+
.to_owned()
84+
}
85+
86+
fn ctor_fn_definition(message: &lib_ruby_parser_nodes::Message) -> String {
87+
let set_fields: Vec<String> = message
88+
.fields
89+
.iter()
90+
.enumerate()
91+
.map(|(idx, f)| {
92+
format!(
93+
"self.Set(\"{name}\", info[{idx}]);",
94+
name = field_name(f),
95+
idx = idx
96+
)
97+
})
98+
.collect();
99+
100+
format!(
101+
"Napi::Value {name}CtorFn(const Napi::CallbackInfo &info)
102+
{{
103+
Napi::Object self = info.This().As<Napi::Object>();
104+
Napi::Env env = info.Env();
105+
(void)self;
106+
{set_fields}
107+
return env.Null();
108+
}}
109+
",
110+
name = message.name,
111+
set_fields = set_fields.join("\n ")
112+
)
113+
}
114+
115+
fn converter(message: &lib_ruby_parser_nodes::Message) -> String {
116+
let fields: Vec<String> = message
117+
.fields
118+
.iter()
119+
.map(|f| {
120+
format!(
121+
"convert(std::move(node->{name}), env),",
122+
name = field_name(f)
123+
)
124+
})
125+
.collect();
126+
127+
format!(
128+
"Napi::Value convert(std::unique_ptr<lib_ruby_parser::{class_name}> node, Napi::Env env) {{
129+
if (!node) {{
130+
return env.Null();
131+
}}
132+
return {class_name}Ctor.New({{
133+
{fields}
134+
}});
135+
}}",
136+
class_name = message.name,
137+
fields = fields.join("\n ")
138+
)
139+
}
140+
fn comparison(message: &lib_ruby_parser_nodes::Message) -> String {
141+
format!(
142+
"if constexpr (std::is_same_v<T, std::unique_ptr<lib_ruby_parser::{class_name}>>) {{
143+
return convert(std::move(variant), env);
144+
}}",
145+
class_name = message.name
146+
)
147+
}
148+
149+
fn init_exports(message: &lib_ruby_parser_nodes::Message) -> String {
150+
format!(
151+
"fn = Napi::Function::New(env, {name}CtorFn, \"{name}\");
152+
{name}Ctor = Napi::Persistent(fn);
153+
{name}Ctor.SuppressDestruct();
154+
exports.Set(\"{name}\", fn);
155+
",
156+
name = message.name
157+
)
158+
}

0 commit comments

Comments
 (0)