From a78d0ecfc3f9e7497521600d75164169f6bd2993 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 19 Oct 2023 00:52:01 +0200 Subject: [PATCH] Add metamethods to doc output --- tool/jml-docgen/README.md | 75 +++++++++++++++++++++++++++++++++++++ tool/jml-docgen/doxygen.lua | 63 +++++++++++++++++++++---------- tool/jml-docgen/main.lua | 75 ++++++++++++++++++++++++++++--------- 3 files changed, 175 insertions(+), 38 deletions(-) diff --git a/tool/jml-docgen/README.md b/tool/jml-docgen/README.md index 17b75e2..92f0289 100644 --- a/tool/jml-docgen/README.md +++ b/tool/jml-docgen/README.md @@ -62,6 +62,7 @@ ## MidiFile ```lua +juce.MidiFile.__eq(...) juce.MidiFile.addTrack(...) juce.MidiFile.clear(...) juce.MidiFile.convertTimestampTicksToSeconds(...) @@ -82,6 +83,7 @@ juce.MidiFile.writeTo(...) ## MidiMessage ```lua +juce.MidiMessage.__eq(...) juce.MidiMessage.addToTimeStamp(...) juce.MidiMessage.aftertouchChange(...) juce.MidiMessage.allControllersOff(...) @@ -185,6 +187,7 @@ juce.MidiMessage.withTimeStamp(...) ## MidiMessageSequence ```lua +juce.MidiMessageSequence.__eq(...) juce.MidiMessageSequence.addTimeToMessages(...) juce.MidiMessageSequence.clear(...) juce.MidiMessageSequence.createControllerUpdatesForTime(...) @@ -211,6 +214,7 @@ juce.MidiMessageSequence.updateMatchedPairs(...) ## MidiRPNDetector ```lua +juce.MidiRPNDetector.__eq(...) juce.MidiRPNDetector.new(...) juce.MidiRPNDetector.reset(...) juce.MidiRPNDetector.tryParse(...) @@ -219,6 +223,7 @@ juce.MidiRPNDetector.tryParse(...) ## MidiRPNMessage ```lua +juce.MidiRPNMessage.__eq(...) juce.MidiRPNMessage.channel(...) juce.MidiRPNMessage.is14BitValue(...) juce.MidiRPNMessage.isNRPN(...) @@ -232,6 +237,9 @@ juce.MidiRPNMessage.value(...) ## BigInteger ```lua +juce.BigInteger.__eq(...) +juce.BigInteger.__le(...) +juce.BigInteger.__lt(...) juce.BigInteger.clear(...) juce.BigInteger.clearBit(...) juce.BigInteger.compare(...) @@ -271,6 +279,8 @@ juce.BigInteger.toString(...) ## File ```lua +juce.File.__eq(...) +juce.File.__lt(...) juce.File.addTrailingSeparator(...) juce.File.appendData(...) juce.File.appendText(...) @@ -357,6 +367,10 @@ juce.File.withFileExtension(...) ## IPAddress ```lua +juce.IPAddress.__eq(...) +juce.IPAddress.__le(...) +juce.IPAddress.__lt(...) +juce.IPAddress.__tostring(...) juce.IPAddress.address(...) juce.IPAddress.any(...) juce.IPAddress.broadcast(...) @@ -378,6 +392,7 @@ juce.IPAddress.toString(...) ## InputStream ```lua +juce.InputStream.__eq(...) juce.InputStream.getNumBytesRemaining(...) juce.InputStream.getPosition(...) juce.InputStream.getTotalLength(...) @@ -407,6 +422,10 @@ juce.InputStream.skipNextBytes(...) ## MemoryBlock ```lua +juce.MemoryBlock.__eq(...) +juce.MemoryBlock.__le(...) +juce.MemoryBlock.__lt(...) +juce.MemoryBlock.__tostring(...) juce.MemoryBlock.append(...) juce.MemoryBlock.copyFrom(...) juce.MemoryBlock.copyTo(...) @@ -433,6 +452,7 @@ juce.MemoryBlock.toString(...) ## MemoryInputStream ```lua +juce.MemoryInputStream.__eq(...) juce.MemoryInputStream.getData(...) juce.MemoryInputStream.getDataSize(...) juce.MemoryInputStream.new(...) @@ -441,6 +461,8 @@ juce.MemoryInputStream.new(...) ## MemoryOutputStream ```lua +juce.MemoryOutputStream.__eq(...) +juce.MemoryOutputStream.__tostring(...) juce.MemoryOutputStream.appendUTF8Char(...) juce.MemoryOutputStream.getData(...) juce.MemoryOutputStream.getDataSize(...) @@ -455,6 +477,7 @@ juce.MemoryOutputStream.toUTF8(...) ## OutputStream ```lua +juce.OutputStream.__eq(...) juce.OutputStream.flush(...) juce.OutputStream.getNewLineString(...) juce.OutputStream.getPosition(...) @@ -484,6 +507,7 @@ juce.OutputStream.writeText(...) ## Random ```lua +juce.Random.__eq(...) juce.Random.getSeed(...) juce.Random.getSystemRandom(...) juce.Random.new(...) @@ -498,6 +522,9 @@ juce.Random.setSeed(...) ## RelativeTime ```lua +juce.RelativeTime.__eq(...) +juce.RelativeTime.__le(...) +juce.RelativeTime.__lt(...) juce.RelativeTime.days(...) juce.RelativeTime.getApproximateDescription(...) juce.RelativeTime.getDescription(...) @@ -518,6 +545,7 @@ juce.RelativeTime.weeks(...) ## Result ```lua +juce.Result.__eq(...) juce.Result.fail(...) juce.Result.failed(...) juce.Result.getErrorMessage(...) @@ -528,6 +556,10 @@ juce.Result.wasOk(...) ## String ```lua +juce.String.__eq(...) +juce.String.__le(...) +juce.String.__lt(...) +juce.String.__tostring(...) juce.String.append(...) juce.String.clear(...) juce.String.compareIgnoreCase(...) @@ -593,6 +625,10 @@ juce.String.upToLastOccurrenceOf(...) ## StringArray ```lua +juce.StringArray.__eq(...) +juce.StringArray.__le(...) +juce.StringArray.__len(...) +juce.StringArray.__lt(...) juce.StringArray.add(...) juce.StringArray.addLines(...) juce.StringArray.appendNumbersToDuplicates(...) @@ -620,6 +656,9 @@ juce.StringArray.trim(...) ## Time ```lua +juce.Time.__eq(...) +juce.Time.__le(...) +juce.Time.__lt(...) juce.Time.currentTimeMillis(...) juce.Time.formatted(...) juce.Time.fromISO8601(...) @@ -657,6 +696,10 @@ juce.Time.waitForMillisecondCounter(...) ## Uuid ```lua +juce.Uuid.__eq(...) +juce.Uuid.__le(...) +juce.Uuid.__lt(...) +juce.Uuid.__tostring(...) juce.Uuid.getClockSeqAndReserved(...) juce.Uuid.getClockSeqLow(...) juce.Uuid.getNode(...) @@ -674,6 +717,8 @@ juce.Uuid.toString(...) ## XmlElement ```lua +juce.XmlElement.__eq(...) +juce.XmlElement.__tostring(...) juce.XmlElement.compareAttribute(...) juce.XmlElement.getAllSubText(...) juce.XmlElement.getAttributeName(...) @@ -711,6 +756,7 @@ juce.XmlElement.setText(...) ## UndoManager ```lua +juce.UndoManager.__eq(...) juce.UndoManager.beginNewTransaction(...) juce.UndoManager.canRedo(...) juce.UndoManager.canUndo(...) @@ -738,6 +784,7 @@ juce.UndoManager.undoCurrentTransactionOnly(...) ## ValueTree ```lua +juce.ValueTree.__eq(...) juce.ValueTree.addChild(...) juce.ValueTree.addListener(...) juce.ValueTree.appendChild(...) @@ -789,6 +836,7 @@ juce.ValueTree.writeToStream(...) ## Timer ```lua +juce.Timer.__eq(...) juce.Timer.new(...) juce.Timer.timerCallback(...) ``` @@ -798,6 +846,7 @@ juce.Timer.timerCallback(...) ## AffineTransform ```lua +juce.AffineTransform.__eq(...) juce.AffineTransform.followedBy(...) juce.AffineTransform.getDeterminant(...) juce.AffineTransform.getTranslationX(...) @@ -825,12 +874,15 @@ juce.AffineTransform.withAbsoluteTranslation(...) ## Colour ```lua +juce.Colour.__eq(...) +juce.Colour.__tostring(...) juce.Colour.new(...) ``` ## ColourGradient ```lua +juce.ColourGradient.__eq(...) juce.ColourGradient.addColour(...) juce.ColourGradient.clearColours(...) juce.ColourGradient.getColour(...) @@ -853,6 +905,7 @@ juce.ColourGradient.vertical(...) ## DropShadow ```lua +juce.DropShadow.__eq(...) juce.DropShadow.colour(...) juce.DropShadow.drawForImage(...) juce.DropShadow.drawForPath(...) @@ -865,6 +918,7 @@ juce.DropShadow.radius(...) ## FillType ```lua +juce.FillType.__eq(...) juce.FillType.colour(...) juce.FillType.getOpacity(...) juce.FillType.image(...) @@ -884,6 +938,8 @@ juce.FillType.transformed(...) ## Font ```lua +juce.Font.__eq(...) +juce.Font.__tostring(...) juce.Font.getAvailableStyles(...) juce.Font.getTypefaceName(...) juce.Font.getTypefaceStyle(...) @@ -896,6 +952,7 @@ juce.Font.withTypefaceStyle(...) ## Graphics ```lua +juce.Graphics.__eq(...) juce.Graphics.addTransform(...) juce.Graphics.beginTransparencyLayer(...) juce.Graphics.clipRegionIntersects(...) @@ -944,6 +1001,7 @@ juce.Graphics.strokePath(...) ## Image ```lua +juce.Image.__eq(...) juce.Image.clear(...) juce.Image.convertedToFormat(...) juce.Image.createCopy(...) @@ -977,6 +1035,8 @@ juce.Image.setPixelAt(...) ## Path ```lua +juce.Path.__eq(...) +juce.Path.__tostring(...) juce.Path.addArc(...) juce.Path.addArrow(...) juce.Path.addBubble(...) @@ -1017,12 +1077,14 @@ juce.Path.writePathToStream(...) ## ArrowButton ```lua +juce.ArrowButton.__eq(...) juce.ArrowButton.new(...) ``` ## Button ```lua +juce.Button.__eq(...) juce.Button.getBounds(...) juce.Button.getHeight(...) juce.Button.getWidth(...) @@ -1035,6 +1097,7 @@ juce.Button.onClick(...) ## ComboBox ```lua +juce.ComboBox.__eq(...) juce.ComboBox.addItem(...) juce.ComboBox.addItemList(...) juce.ComboBox.addListener(...) @@ -1073,6 +1136,7 @@ juce.ComboBox.showPopup(...) ## ComponentListener ```lua +juce.ComponentListener.__eq(...) juce.ComponentListener.componentBeingDeleted(...) juce.ComponentListener.componentBroughtToFront(...) juce.ComponentListener.componentChildrenChanged(...) @@ -1087,6 +1151,7 @@ juce.ComponentListener.new(...) ## Grid ```lua +juce.Grid.__eq(...) juce.Grid.alignContent(...) juce.Grid.alignItems(...) juce.Grid.autoColumns(...) @@ -1110,6 +1175,7 @@ juce.Grid.templateRows(...) ## HyperlinkButton ```lua +juce.HyperlinkButton.__eq(...) juce.HyperlinkButton.changeWidthToFitText(...) juce.HyperlinkButton.getJustificationType(...) juce.HyperlinkButton.getURL(...) @@ -1122,6 +1188,7 @@ juce.HyperlinkButton.setURL(...) ## ImageComponent ```lua +juce.ImageComponent.__eq(...) juce.ImageComponent.getImage(...) juce.ImageComponent.getImagePlacement(...) juce.ImageComponent.new(...) @@ -1132,6 +1199,7 @@ juce.ImageComponent.setImagePlacement(...) ## Label ```lua +juce.Label.__eq(...) juce.Label.addListener(...) juce.Label.attachToComponent(...) juce.Label.doesLossOfFocusDiscardChanges(...) @@ -1164,6 +1232,7 @@ juce.Label.showEditor(...) ## LookAndFeel ```lua +juce.LookAndFeel.__eq(...) juce.LookAndFeel.createDropShadowerForComponent(...) juce.LookAndFeel.createGraphicsContext(...) juce.LookAndFeel.drawSpinningWaitAnimation(...) @@ -1184,6 +1253,7 @@ juce.LookAndFeel.setUsingNativeAlertWindows(...) ## LookAndFeel_V4 ```lua +juce.LookAndFeel_V4.__eq(...) juce.LookAndFeel_V4.drawButtonBackground(...) juce.LookAndFeel_V4.drawToggleButton(...) juce.LookAndFeel_V4.getTextButtonFont(...) @@ -1193,6 +1263,7 @@ juce.LookAndFeel_V4.new(...) ## Slider ```lua +juce.Slider.__eq(...) juce.Slider.addListener(...) juce.Slider.getCurrentPopupDisplay(...) juce.Slider.getDoubleClickReturnValue(...) @@ -1271,12 +1342,14 @@ juce.Slider.valueToProportionOfLength(...) ## TextButton ```lua +juce.TextButton.__eq(...) juce.TextButton.new(...) ``` ## ToggleButton ```lua +juce.ToggleButton.__eq(...) juce.ToggleButton.changeWidthToFitText(...) juce.ToggleButton.new(...) ``` @@ -1284,6 +1357,7 @@ juce.ToggleButton.new(...) ## TreeView ```lua +juce.TreeView.__eq(...) juce.TreeView.areItemsOpenByDefault(...) juce.TreeView.areOpenCloseButtonsVisible(...) juce.TreeView.clearSelectedItems(...) @@ -1318,6 +1392,7 @@ juce.TreeView.setRootItemVisible(...) ## CodeDocument ```lua +juce.CodeDocument.__eq(...) juce.CodeDocument.addListener(...) juce.CodeDocument.applyChanges(...) juce.CodeDocument.clearUndoHistory(...) diff --git a/tool/jml-docgen/doxygen.lua b/tool/jml-docgen/doxygen.lua index ef281f4..de5e5cb 100644 --- a/tool/jml-docgen/doxygen.lua +++ b/tool/jml-docgen/doxygen.lua @@ -2,6 +2,12 @@ json = require("json") local doxygen = {} +local function has_kind(e, expected_kind) + local tag = juce.String.new("kind") + local kind = e:getStringAttribute(juce.StringRef.new(tag)) + return tostring(kind) == expected_kind +end + local function select_xml_file(entity) entity = entity:gsub('_', '__') local juce_root = "~/Developer/tobiashienzsch/JUCE" @@ -45,13 +51,9 @@ local function parse_function_parameter(func) end local function parse_member_function(e) - local empty = juce.String.new("") + assert(has_kind(e, "function")) - local kind_tag = juce.String.new("kind") - local kind = e:getStringAttribute(juce.StringRef.new(kind_tag)) - assert(tostring(kind) == "function") - - local mem_fun = { + return { name = get_all_text(e, "name"), brief = get_all_text(e, "briefdescription"), detail = get_all_text(e, "detaileddescription"), @@ -62,11 +64,37 @@ local function parse_member_function(e) return_type = get_all_text(e, "type"), parameter = parse_function_parameter(e), } +end - return mem_fun +local function parse_member_variable(e) + assert(has_kind(e, "variable")) + + return { + name = get_all_text(e, "name"), + type = get_all_text(e, "type"), + brief = get_all_text(e, "briefdescription"), + detail = get_all_text(e, "detaileddescription"), + is_static = get_bool(e, "static"), + } end function doxygen.parse_xml(entity_name) + -- Results + local results = {name = "", brief = "", members = {}, variables = {}} + + local add_function = function(e) + table.insert(results.members, parse_member_function(e)) + end + local add_variable = function(e) + table.insert(results.variables, parse_member_variable(e)) + end + local section_parsers = { + ["public-func"] = add_function, + ["public-static-func"] = add_function, + ["public-attrib"] = add_variable, + ["public-static-attrib"] = add_variable, + } + -- Xml file local xml_file = select_xml_file(entity_name) assert(xml_file:existsAsFile()) @@ -81,30 +109,25 @@ function doxygen.parse_xml(entity_name) local kind_tag = juce.String.new("kind") - -- Results - local results = {name = "", brief = "", members = {}} - -- For each child for i = 0, def:getNumChildElements() - 1 do local child = def:getChildElement(i) local tag = tostring(child:getTagName()) if tag == "compoundname" then -- Get name - results["name"] = tostring(child:getAllSubText()) + results["name"] = tostring(child:getAllSubText()):gsub("\n", " ") elseif tag == "briefdescription" then -- Get brief - results["brief"] = tostring(child:getAllSubText()) + results["brief"] = tostring(child:getAllSubText()):gsub("\n", " ") elseif tag == "sectiondef" then - -- Get sections + -- Sections local section = child:getStringAttribute(juce.StringRef.new(kind_tag)) - section = tostring(section) - if (section == "public-func" or section == "public-static-func") then - -- Public functions + local parser = section_parsers[tostring(section)] + if parser then for j = 0, child:getNumChildElements() - 1 do local members = child:getChildElement(j) if tostring(members:getTagName()) == "memberdef" then - local func = parse_member_function(members) - table.insert(results.members, func) + parser(members) end end end @@ -129,8 +152,8 @@ return doxygen -- local ColourGradient = {} -- ---- --- -- Public variables of the class --- -- @table public +-- Public variables of the class +-- @table public -- -- @field Point point1 -- -- @field Point point2 -- -- @field bool isRadial diff --git a/tool/jml-docgen/main.lua b/tool/jml-docgen/main.lua index a15e5a5..e791217 100644 --- a/tool/jml-docgen/main.lua +++ b/tool/jml-docgen/main.lua @@ -1,17 +1,32 @@ doxygen = require("doxygen") sol2 = require("sol2") +local function table_length(T) + local count = 0 + for _ in pairs(T) do + count = count + 1 + end + return count +end + local function starts_with(str, prefix) return string.sub(str, 1, string.len(prefix)) == prefix end local function format_usertype_docs_as_lua_stubs(doc) + local ignored_functions = { + ["__gc"] = true, + ["__pairs"] = true, + ["__newindex"] = true, + ["__index"] = true, + } + local str = string.format("## %s\n\n", doc.name) str = str .. string.format("```lua\n") for i = 1, #doc.members do - member = doc.members[i] - if starts_with(member, "__") == false then - str = str .. string.format("juce.%s.%s(...)\n", doc.name, member) + func = doc.members[i] + if ignored_functions[func] == nil then + str = str .. string.format("juce.%s.%s(...)\n", doc.name, func) end end str = str .. string.format("```\n\n") @@ -21,29 +36,53 @@ end local function write_usertype_as_lua_stubs(dir, modules) local docs, _ = sol2.parse_juce_types(modules) for module_name, juce_module in pairs(docs) do - for entity_name, entity in pairs(juce_module[2]) do - local doxygen_spec = doxygen.parse_xml(entity_name) + for class_name, class in pairs(juce_module[2]) do + local doxygen_spec = doxygen.parse_xml(class_name) if doxygen_spec == nil then - doxygen_spec = {brief = entity_name, members = {}} + doxygen_spec = {brief = class_name, members = {}, variables = {}} end -- Create lua file - local file = io.open(dir .. "/" .. entity_name .. ".lua", "w") + local path = string.format("%s/%s.lua", dir, class_name, ".lua") + local file = io.open(path, "w") if file == nil then - print("error:", entity_name) + print("error:", class_name) end -- Write ldoc headers - local ns = "juce" - + local namespace = "juce" file:write(string.format("--- %s\n", doxygen_spec.brief)) - file:write(string.format("-- @classmod %s.%s\n\n", ns, entity_name)) - file:write(string.format("local %s = {}\n\n", entity_name)) + file:write(string.format("-- @classmod %s.%s\n\n", namespace, class_name)) + file:write(string.format("local %s = {}\n\n", class_name)) + + -- For each variable in class + local members_variables = {} + for _, variable in pairs(doxygen_spec.variables) do + for _, member_name in pairs(class.members) do + if member_name == variable.name then + members_variables[member_name] = true + end + end + end + + if table_length(members_variables) > 0 then + file:write("--- Public variables of the class\n") + file:write("-- @table Variables\n") + for name, var in pairs(members_variables) do + file:write(string.format("-- @field %s\n", name)) + end + file:write("\n\n") + end + + -- For each member in class + for _, member in pairs(class.members) do + local skip = false + if members_variables[member] then + skip = true + end - -- For each member in entity - for _, member in pairs(entity.members) do -- Skip special functions - if starts_with(member, "__") == false then + if not skip then local doxygen_member = nil for _, spec in pairs(doxygen_spec.members) do if spec.name == member then @@ -88,15 +127,15 @@ local function write_usertype_as_lua_stubs(dir, modules) if #doxygen_member.parameter == 0 then local fmt = "function %s%s%s() end\n\n" - file:write(string.format(fmt, entity_name, seperator, member)) + file:write(string.format(fmt, class_name, seperator, member)) else local fmt = "function %s%s%s(...) end\n\n" - file:write(string.format(fmt, entity_name, seperator, member)) + file:write(string.format(fmt, class_name, seperator, member)) end end end - file:write(string.format("return %s\n", entity_name)) + file:write(string.format("return %s\n", class_name)) file:close() end end