From 2f96bd0a8567c78a0bfc00023b76fe443f0748d8 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Wed, 14 Dec 2022 18:41:57 +0100 Subject: [PATCH 1/6] feat(Entity): implement basic type fixer --- src/awesomewm.d.tl/entity/Module_Doc.tl | 8 ++++++ src/awesomewm.d.tl/entity/Type_Info.tl | 32 ++++++++++++++++------ src/awesomewm.d.tl/entity/Variable_Info.tl | 8 ++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/awesomewm.d.tl/entity/Module_Doc.tl b/src/awesomewm.d.tl/entity/Module_Doc.tl index 2d4495f..4e7a6b7 100644 --- a/src/awesomewm.d.tl/entity/Module_Doc.tl +++ b/src/awesomewm.d.tl/entity/Module_Doc.tl @@ -15,6 +15,8 @@ local record Module_Doc properties: List static_functions: List signals: List + + fixup: function(Module_Doc) end local __Module_Doc: metatable = { @@ -25,6 +27,12 @@ local __Module_Doc: metatable = { properties = List(), static_functions = List(), signals = List(), + + fixup = function(self: Module_Doc) + for p in self.properties:iter() do + p:fixup() + end + end, } end, } diff --git a/src/awesomewm.d.tl/entity/Type_Info.tl b/src/awesomewm.d.tl/entity/Type_Info.tl index 1aa2b1e..7a6ba90 100644 --- a/src/awesomewm.d.tl/entity/Type_Info.tl +++ b/src/awesomewm.d.tl/entity/Type_Info.tl @@ -1,6 +1,15 @@ local List = require "pl.List" local Map = require "pl.Map" +local type_fix: Map = Map({ + bool = "boolean", + client = "Client", + image = "Image", + int = "integer", + screen = "Screen", + tag = "Tag", +}) + local record Type_Info metamethod __call: function(Type_Info, record_name: string): Type_Info @@ -11,19 +20,26 @@ local record Type_Info -- Map : name -> type -- We can't use Variable_Info here because it's a circular dependency. record_entries: Map> | nil + + fixup: function(self: Type_Info) end local __Type_Info: metatable = { __call = function(_self: Type_Info, record_name: string): Type_Info - if record_name ~= nil then - return { - name = record_name, - record_entries = Map() - } - end return { - name = "", - record_entries = nil, + name = record_name and record_name or "", + record_entries = record_name and Map() or nil, + + fixup = function(self: Type_Info) + self.name = type_fix:get(self.name) or self.name + if self.record_entries then + for _, types in (self.record_entries as Map>):iter() do + for t in types:iter() do + t:fixup() + end + end + end + end } end, } diff --git a/src/awesomewm.d.tl/entity/Variable_Info.tl b/src/awesomewm.d.tl/entity/Variable_Info.tl index 0469f2d..03f169e 100644 --- a/src/awesomewm.d.tl/entity/Variable_Info.tl +++ b/src/awesomewm.d.tl/entity/Variable_Info.tl @@ -10,6 +10,8 @@ local record Variable_Info types: List constraints: List + + fixup: function(self: Variable_Info) end local __Variable_Info: metatable = { @@ -19,6 +21,12 @@ local __Variable_Info: metatable = { return { name = name, types = types, + + fixup = function(self: Variable_Info) + for t in self.types:iter() do + t:fixup() + end + end, } end, } -- 2.40.1 From 5709219a7986aecb300767e35504acb65babf46e Mon Sep 17 00:00:00 2001 From: Aire-One Date: Wed, 14 Dec 2022 18:44:19 +0100 Subject: [PATCH 2/6] run: make the program fix types --- src/awesomewm.d.tl/init.tl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/awesomewm.d.tl/init.tl b/src/awesomewm.d.tl/init.tl index 743a5ec..42e638d 100644 --- a/src/awesomewm.d.tl/init.tl +++ b/src/awesomewm.d.tl/init.tl @@ -27,6 +27,7 @@ log:info("Finished Module List scrapping, found " .. #module_infos .. " modules" local function do_one_file(url: string, module_name: string, output: string) local html = crawler.fetch(url) local module_doc = scraper.module_doc.get_doc_from_page(html, module_name) + module_doc:fixup() filesystem.file_writer.write( generator.teal_type_definitions.generate_teal(module_doc), output -- 2.40.1 From 719aa36273c3b20a0666a5e71f95a75183894d41 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Wed, 14 Dec 2022 18:47:01 +0100 Subject: [PATCH 3/6] fix(scraper): produce Type_Info --- src/awesomewm.d.tl/scraper/module_doc.tl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/awesomewm.d.tl/scraper/module_doc.tl b/src/awesomewm.d.tl/scraper/module_doc.tl index 81e58dd..ac1d1c8 100644 --- a/src/awesomewm.d.tl/scraper/module_doc.tl +++ b/src/awesomewm.d.tl/scraper/module_doc.tl @@ -18,13 +18,13 @@ end local function parse_parameter_types(parameter_type: string): List if parameter_type == "" then - local type_info: Type_Info.Type_Info = { name = "any" } + local type_info: Type_Info.Type_Info = Type_Info("any" ) return List({ type_info }) end return stringx.split(parameter_type, " or "):map( function(type_name: string): Type_Info.Type_Info - return { name = utils.sanitize_string(type_name) } + return Type_Info(utils.sanitize_string(type_name)) end ) end -- 2.40.1 From 766849d5fcd2f03097525ceaec5a2b2dac880873 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Mon, 19 Dec 2022 18:00:51 +0100 Subject: [PATCH 4/6] fix(Entity): fixup() for Function_Info This commit also force all functions from the `scraper` module to instantiate every entity types they returns. We no longer accept floating objects as instance. It was causing issues because they hadn't the expected methods defined. --- src/awesomewm.d.tl/entity/Function_Info.tl | 50 +++++++++++------- src/awesomewm.d.tl/entity/Module_Doc.tl | 3 ++ src/awesomewm.d.tl/generator/snippets.tl | 14 +++-- src/awesomewm.d.tl/scraper/module_doc.tl | 61 ++++++++++------------ 4 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/awesomewm.d.tl/entity/Function_Info.tl b/src/awesomewm.d.tl/entity/Function_Info.tl index 6b8c821..d8605ad 100644 --- a/src/awesomewm.d.tl/entity/Function_Info.tl +++ b/src/awesomewm.d.tl/entity/Function_Info.tl @@ -1,42 +1,56 @@ local List = require "pl.List" local Type_Info = require "entity.Type_Info" +local Variable_Info = require "entity.Variable_Info" local record Function_Info - metamethod __call: function(Function_Info): Function_Info + metamethod __call: function( + Function_Info, + name: string, + parameters: List, + return_types: List + ): Function_Info Function_Info: Function_Info - record Parameter - name: string - types: List - end name: string - parameters: List - return_types: List + parameters: List + return_types: List append_parameter: function(self: Function_Info, name: string, type: string) append_return_type: function(self: Function_Info, return_type: string) + + fixup: function(Function_Info) end local __Function_Info: metatable = { - __call = function(_self: Function_Info): Function_Info - return { - name = "", - parameters = List(), - return_types = List(), - } + __call = function( + _self: Function_Info, + name: string, + parameters: List, + return_types: List): Function_Info + return { + name = name or "", + parameters = parameters or (List() as List), + return_types = return_types or (List() as List), + + fixup = function(self: Function_Info) + for p in self.parameters:iter() do + p:fixup() + end + for r in self.return_types:iter() do + r:fixup() + end + end, + } end, } function Function_Info:append_parameter(name: string, types: List) - self.parameters:append { - name = name, - types = types, - } + self.parameters:append(Variable_Info(name, types)) end function Function_Info:append_return_type(return_type: string) - self.return_types:append(return_type) + self.return_types:append(Type_Info(return_type)) end return setmetatable({} as Function_Info, __Function_Info) diff --git a/src/awesomewm.d.tl/entity/Module_Doc.tl b/src/awesomewm.d.tl/entity/Module_Doc.tl index 4e7a6b7..896701e 100644 --- a/src/awesomewm.d.tl/entity/Module_Doc.tl +++ b/src/awesomewm.d.tl/entity/Module_Doc.tl @@ -32,6 +32,9 @@ local __Module_Doc: metatable = { for p in self.properties:iter() do p:fixup() end + for m in self.methods:iter() do + m:fixup() + end end, } end, diff --git a/src/awesomewm.d.tl/generator/snippets.tl b/src/awesomewm.d.tl/generator/snippets.tl index 7eb86df..1a2c4e2 100644 --- a/src/awesomewm.d.tl/generator/snippets.tl +++ b/src/awesomewm.d.tl/generator/snippets.tl @@ -15,7 +15,7 @@ local record Module render_enum: function(name: string, values: List): string render_record_properties: function(items: List): string render_record: function(name: string, items: List): string - render_records_from_Parameters: function(items: List): string + render_records_from_Parameters: function(items: List): string end @@ -44,17 +44,21 @@ function snippets.render_anonymous_function_signature(item: Function_Info.Functi local tmpl_args = { function_name = item.name, - function_parameter = item.parameters:map(function(param: Function_Info.Parameter): string + function_parameter = item.parameters:map(function(param: Variable_Info.Variable_Info): string return snippets.render_typed_variable(param.name, param.types) end):concat(", "), - function_return = item.return_types:concat(", "), + function_return = item.return_types:map( + function(return_type: Type_Info.Type_Info): string + return return_type.name + end + ):concat(", "), } return utils.do_or_fail(template.substitute, tmpl, tmpl_args) end -function snippets.render_records_from_Parameters(items: List): string - return items:map(function(param: Function_Info.Parameter): string +function snippets.render_records_from_Parameters(items: List): string + return items:map(function(param: Variable_Info.Variable_Info): string if #param.types == 0 then return "" end diff --git a/src/awesomewm.d.tl/scraper/module_doc.tl b/src/awesomewm.d.tl/scraper/module_doc.tl index ac1d1c8..a92740b 100644 --- a/src/awesomewm.d.tl/scraper/module_doc.tl +++ b/src/awesomewm.d.tl/scraper/module_doc.tl @@ -18,7 +18,7 @@ end local function parse_parameter_types(parameter_type: string): List if parameter_type == "" then - local type_info: Type_Info.Type_Info = Type_Info("any" ) + local type_info: Type_Info.Type_Info = Type_Info("any") return List({ type_info }) end @@ -33,7 +33,7 @@ local function extract_item_name(item_name_node: scan.HTMLNode): string return item_name_node and ((item_name_node.attr.name as string):gsub("^.*[%.:]", "")) end -local function extract_function_parameter_Parameters(tr_node: scan.HTMLNode): { Function_Info.Parameter } +local function extract_function_parameter_Parameters(tr_node: scan.HTMLNode): { Variable_Info.Variable_Info } local query_selectors = { name = "span.parameter", types = "span.types" @@ -42,21 +42,21 @@ local function extract_function_parameter_Parameters(tr_node: scan.HTMLNode): { return scraper_utils.scrape_tuples( tr_node:outer_html(), { query_selectors.name, query_selectors.types }, - function(nodes: { string : scan.HTMLNode | nil }): Function_Info.Parameter - return { - name = extract_node_text(nodes[query_selectors.name] as scan.HTMLNode), - types = parse_parameter_types(extract_node_text(nodes[query_selectors.types] as scan.HTMLNode)), - } + function(nodes: { string : scan.HTMLNode | nil }): Variable_Info.Variable_Info + return Variable_Info( + extract_node_text(nodes[query_selectors.name] as scan.HTMLNode), + parse_parameter_types(extract_node_text(nodes[query_selectors.types] as scan.HTMLNode)) + ) end) end -local function extract_function_parameters(function_parameters_node: scan.HTMLNode): { Function_Info.Parameter } +local function extract_function_parameters(function_parameters_node: scan.HTMLNode): { Variable_Info.Variable_Info } local current_record_parameter: Type_Info.Type_Info | nil = nil return scraper_utils.scrape( function_parameters_node:outer_html(), "tr", - function(line_node: scan.HTMLNode): Function_Info.Parameter + function(line_node: scan.HTMLNode): Variable_Info.Variable_Info local parameters = extract_function_parameter_Parameters(line_node) if #parameters == 0 then return nil @@ -81,20 +81,17 @@ local function extract_function_parameters(function_parameters_node: scan.HTMLNo if #types == 1 and types[1].name == "table" then local record_name = utils.capitalize(name) current_record_parameter = Type_Info(record_name) - return { - name = name, - types = List({ current_record_parameter }), - } + return Variable_Info( + name, + List({ current_record_parameter }) + ) end - return { - name = name, - types = types, - } + return Variable_Info(name, types) end) end -local function extract_function_return_types(function_return_types_node: scan.HTMLNode): { string } +local function extract_function_return_types(function_return_types_node: scan.HTMLNode): List if not function_return_types_node then return {} end @@ -102,7 +99,10 @@ local function extract_function_return_types(function_return_types_node: scan.HT local selector = "span.types .type" local html = function_return_types_node:outer_html() - return scraper_utils.scrape(html, selector, extract_node_text) + return List(scraper_utils.scrape(html, selector, extract_node_text)):map( + function(type_name: string): Type_Info.Type_Info + return Type_Info(type_name) + end) end local function extract_property_constraints(property_constraint_node: scan.HTMLNode): { string } @@ -141,19 +141,19 @@ local function extract_section_functions(dl: string): { Function_Info.Function_I body:outer_html(), { query_selectors.parameters, query_selectors.return_types } ) - return { - name = scraper_utils.scrape( + return Function_Info( + scraper_utils.scrape( header:outer_html(), query_selectors.name, extract_item_name )[1], - parameters = #body_elements:get(query_selectors.parameters) ~= 0 and + #body_elements:get(query_selectors.parameters) ~= 0 and List(extract_function_parameters(body_elements:get(query_selectors.parameters)[1])) or - (List() as List), - return_types = #body_elements:get(query_selectors.return_types) ~= 0 and - List(extract_function_return_types(body_elements:get(query_selectors.return_types)[1])) or - (List() as List), - } + (List() as List), + #body_elements:get(query_selectors.return_types) ~= 0 and + extract_function_return_types(body_elements:get(query_selectors.return_types)[1]) or + (List() as List) + ) end ) end @@ -209,11 +209,8 @@ function module.get_doc_from_page(html: string, module_name: string): Module_Doc local module_doc = Module_Doc() module_doc.record_name = utils.capitalize((module_name:gsub(".*%.", ""))) - local self_type: Type_Info.Type_Info = { name = module_doc.record_name } - local self_parameter: Function_Info.Parameter = { - name = "self", - types = List({ self_type }), - } + local self_type = Type_Info(module_doc.record_name) + local self_parameter = Variable_Info("self", List({ self_type })) for i = 1, #nodes:get("h2.section-header") do local h2 = nodes:get("h2.section-header")[i] -- 2.40.1 From 67ecf460581c18e3886dd955f60bd794f2bbd280 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Mon, 19 Dec 2022 18:13:20 +0100 Subject: [PATCH 5/6] feat(Module_Doc): more fixup --- src/awesomewm.d.tl/entity/Module_Doc.tl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/awesomewm.d.tl/entity/Module_Doc.tl b/src/awesomewm.d.tl/entity/Module_Doc.tl index 896701e..02cf186 100644 --- a/src/awesomewm.d.tl/entity/Module_Doc.tl +++ b/src/awesomewm.d.tl/entity/Module_Doc.tl @@ -29,12 +29,22 @@ local __Module_Doc: metatable = { signals = List(), fixup = function(self: Module_Doc) - for p in self.properties:iter() do - p:fixup() + for c in self.constructors:iter() do + c:fixup() + if #c.return_types == 1 then + c.return_types[1].name = self.record_name + end end for m in self.methods:iter() do m:fixup() end + for p in self.properties:iter() do + p:fixup() + end + for s in self.static_functions:iter() do + s:fixup() + end + end, } end, -- 2.40.1 From dc8698270b73bcb2130ea6d29b16ec517e8801c0 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Mon, 19 Dec 2022 19:39:34 +0100 Subject: [PATCH 6/6] feat(Module_Doc): manage requires --- src/awesomewm.d.tl/entity/Module_Doc.tl | 65 ++++++++++++++++++- src/awesomewm.d.tl/entity/Type_Info.tl | 8 ++- src/awesomewm.d.tl/generator/snippets.tl | 17 +++++ .../generator/teal_type_definitions.tl | 4 ++ src/awesomewm.d.tl/init.tl | 1 + 5 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/awesomewm.d.tl/entity/Module_Doc.tl b/src/awesomewm.d.tl/entity/Module_Doc.tl index 02cf186..612df1b 100644 --- a/src/awesomewm.d.tl/entity/Module_Doc.tl +++ b/src/awesomewm.d.tl/entity/Module_Doc.tl @@ -1,7 +1,14 @@ local Function_Info = require "entity.Function_Info" local List = require "pl.List" +local Map = require "pl.Map" local Variable_Info = require "entity.Variable_Info" +local module_to_require : Map = Map({ + Shape = "gears.shape", + Surface = "gears.surface", + Widget = "wibox.widget", +}) + local record Module_Doc metamethod __call: function(Module_Doc): Module_Doc @@ -16,7 +23,10 @@ local record Module_Doc static_functions: List signals: List + requires: Map + fixup: function(Module_Doc) + populate_requires: function(Module_Doc) end local __Module_Doc: metatable = { @@ -27,6 +37,7 @@ local __Module_Doc: metatable = { properties = List(), static_functions = List(), signals = List(), + requires = Map(), fixup = function(self: Module_Doc) for c in self.constructors:iter() do @@ -44,8 +55,60 @@ local __Module_Doc: metatable = { for s in self.static_functions:iter() do s:fixup() end - end, + populate_requires = function(self: Module_Doc) + -- TODO : Move this to other Entities. Can be a little tricky because we populate a map + for c in self.constructors:iter() do + for p in c.parameters:iter() do + for t in p.types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + end + for m in self.methods:iter() do + for p in m.parameters:iter() do + for t in p.types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + for t in m.return_types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + for p in self.properties:iter() do + for t in p.types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + for s in self.static_functions:iter() do + for p in s.parameters:iter() do + for t in p.types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + for t in s.return_types:iter() do + local mod = module_to_require:get(t.name) + if mod then + self.requires:set(t.name, mod) + end + end + end + end } end, } diff --git a/src/awesomewm.d.tl/entity/Type_Info.tl b/src/awesomewm.d.tl/entity/Type_Info.tl index 7a6ba90..819a0a6 100644 --- a/src/awesomewm.d.tl/entity/Type_Info.tl +++ b/src/awesomewm.d.tl/entity/Type_Info.tl @@ -1,13 +1,19 @@ local List = require "pl.List" local Map = require "pl.Map" -local type_fix: Map = Map({ +local type_fix : Map = Map({ bool = "boolean", client = "Client", + ["gears.shape"] = "Shape", + ["gears.surface"] = "Surface", image = "Image", int = "integer", screen = "Screen", + shape = "Shape", + surface = "Surface", tag = "Tag", + ["wibox.widget"] = "Widget", + widget = "Widget", }) local record Type_Info diff --git a/src/awesomewm.d.tl/generator/snippets.tl b/src/awesomewm.d.tl/generator/snippets.tl index 1a2c4e2..7d3209b 100644 --- a/src/awesomewm.d.tl/generator/snippets.tl +++ b/src/awesomewm.d.tl/generator/snippets.tl @@ -9,6 +9,7 @@ local Variable_Info = require "entity.Variable_Info" local record Module indent: function(str: string, level: number): string + render_requires: function(requires: Map): string render_typed_variable: function(name: string, types: List): string render_anonymous_function_signature: function(item: Function_Info.Function_Info): string render_record_functions: function(items: List): string @@ -26,6 +27,22 @@ function snippets.indent(str: string, level: number): string return stringx.rstrip(stringx.indent(str, level, string.rep(" ", 3))) end +function snippets.render_requires(requires: Map): string + local tmpl = [[local $(name) = require "$(path)"]] + + local require_statements = List() + for name, path in requires:iter() do + local tmpl_args = { + name = name, + path = path, + } + + require_statements:append(utils.do_or_fail(template.substitute, tmpl, tmpl_args)) + end + + return require_statements:concat("\n") +end + function snippets.render_typed_variable(name: string, types: List): string local tmpl = [[$(name): $(types)]] diff --git a/src/awesomewm.d.tl/generator/teal_type_definitions.tl b/src/awesomewm.d.tl/generator/teal_type_definitions.tl index 1697d0b..0a1d31a 100644 --- a/src/awesomewm.d.tl/generator/teal_type_definitions.tl +++ b/src/awesomewm.d.tl/generator/teal_type_definitions.tl @@ -8,6 +8,10 @@ local snippets = require "generator.snippets" local tmpl = [[ -- Auto generated file (Do not manually edit this file!) +# if module.requires:len() ~= 0 then +$(snippets.render_requires(module.requires)) +# end -- /requires + local record $(module.record_name) # if #module.signals ~= 0 then $(snippets.indent(snippets.render_enum("Signal", module.signals))) diff --git a/src/awesomewm.d.tl/init.tl b/src/awesomewm.d.tl/init.tl index 42e638d..e5156ae 100644 --- a/src/awesomewm.d.tl/init.tl +++ b/src/awesomewm.d.tl/init.tl @@ -28,6 +28,7 @@ local function do_one_file(url: string, module_name: string, output: string) local html = crawler.fetch(url) local module_doc = scraper.module_doc.get_doc_from_page(html, module_name) module_doc:fixup() + module_doc:populate_requires() filesystem.file_writer.write( generator.teal_type_definitions.generate_teal(module_doc), output -- 2.40.1