From 5d3602383705ef28eaffb8d133803454b30bbe1b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 11 Mar 2026 15:21:35 +0100 Subject: [PATCH] Allow documenting function via comment on DeclareGlobalName Keep DeclareGlobalName entries documented as variables by default, but promote them to functions when @Arguments or @Returns provides function-style documentation. Preserve explicit @ItemType overrides and document the resulting behavior in the manual and regression fixtures. AI assistance disclosure: Codex assisted with implementing the parser change, updating the manual text, and revising the test fixtures and expected output. Co-authored-by: Codex --- CHANGES.md | 3 ++ doc/Comments.autodoc | 13 +++++- gap/Parser.gi | 33 +++++++++++-- tst/errorwithpos.tst | 2 +- tst/manual.expected/_Chapter_Comments.xml | 13 +++++- tst/misc.tst | 46 +++++++++++++++++++ .../general.expected/_Chapter_SomeChapter.xml | 9 +++- tst/worksheets/general.sheet/worksheet.g | 7 ++- 8 files changed, 116 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7b2a9d6f..056f3676 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,9 @@ This file describes changes in the AutoDoc package. - Document `InstallMethod` support in declaration comments and add `@ItemType` to override whether an installed method should be documented as `Func`, `Oper`, `Attr`, or `Prop` + - Improve `DeclareGlobalName` handling: document it as a variable by + default, but switch to a function when `@Arguments` or `@Returns` + provides function-style documentation - Loosen requirements on `@Date` command: this used to allow free form, but in recent versions was restricted to dates of the form YYYY-MM-DD or DD/MM/YYYY; now we again allow any text, but text in those specific diff --git a/doc/Comments.autodoc b/doc/Comments.autodoc index b9c6d705..1132db8b 100644 --- a/doc/Comments.autodoc +++ b/doc/Comments.autodoc @@ -80,13 +80,18 @@ square brackets for the optional arguments, like grp[, elm] or xx[y[z] ]. If &GAP; options are used, this can be followed by a colon : and one or more assignments, like n[, r]: tries := 100. +For DeclareGlobalName, using @Arguments or @Returns also +makes &AutoDoc; document the item as a function. This is useful because +DeclareGlobalName itself does not reveal whether the name denotes a +function or a variable. + @Subsection @ItemType kind @SubsectionLabel @ItemType @Index "@ItemType" @ItemType kind Overrides the kind of manual item created for the following declaration or installed method. The supported values are Func, Oper, -Attr, and Prop. +Attr, Prop, and Var. This is mainly useful for InstallMethod. For a declaration such as DeclareAttribute or DeclareProperty, &AutoDoc; already knows the @@ -95,6 +100,12 @@ especially with one argument, the source code alone does not reliably tell whether the method belongs to an operation, an attribute, a property, or even a plain function. Without an override, such entries default to Oper. +It is also useful for DeclareGlobalName, because that declaration can +refer to either a function or a variable. &AutoDoc; defaults such entries to +Var, but switches to Func as soon as @Arguments or +@Returns indicates function-style documentation. You can still use +@ItemType to override this explicitly. + For example: ```@listing diff --git a/gap/Parser.gi b/gap/Parser.gi index 30675f32..a581243c 100644 --- a/gap/Parser.gi +++ b/gap/Parser.gi @@ -173,10 +173,19 @@ InstallGlobalFunction( AutoDoc_Type_Of_Item, item_rec!.arguments := fail; item_rec!.return_value := false; elif PositionSublist( type, "DeclareGlobalName" ) <> fail then - entries := [ "Var", "global_variables" ]; has_filters := "No"; - item_rec!.arguments := fail; - item_rec!.return_value := false; + if ( IsBound( item_rec!.item_type ) and item_rec!.item_type <> "Var" ) or + ( IsBound( item_rec!.declareglobalname_is_function ) and + item_rec!.declareglobalname_is_function ) then + entries := [ "Func", "global_functions" ]; + if not IsBound( item_rec!.arguments ) then + item_rec!.arguments := "arg"; + fi; + else + entries := [ "Var", "global_variables" ]; + item_rec!.arguments := fail; + item_rec!.return_value := false; + fi; elif PositionSublist( type, "DeclareFilter" ) <> fail then entries := [ "Filt", "properties" ]; has_filters := "No"; @@ -422,13 +431,13 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, end; NormalizeItemType := function( item_type ) item_type := StripBeginEnd( item_type, " \t\r\n" ); - if item_type in [ "Func", "Oper", "Attr", "Prop" ] then + if item_type in [ "Func", "Oper", "Attr", "Prop", "Var" ] then return item_type; fi; ErrorWithPos( Concatenation( "unknown @ItemType ", item_type, - "; expected one of Func, Oper, Attr, Prop" + "; expected one of Func, Oper, Attr, Prop, Var" ) ); end; @@ -806,12 +815,26 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, @Returns := function() CurrentOrNewManItem(); CurrentItem()!.content := CurrentItem()!.return_value; + if IsBound( CurrentItem()!.item_type ) and CurrentItem()!.item_type = "Var" then + CurrentItem()!.item_type := "Func"; + if not IsBound( CurrentItem()!.arguments ) or CurrentItem()!.arguments = fail then + CurrentItem()!.arguments := "arg"; + fi; + CurrentItem()!.return_value := [ ]; + elif not IsBound( CurrentItem()!.item_type ) then + CurrentItem()!.declareglobalname_is_function := true; + fi; if current_command[ 2 ] <> "" then Add( CurrentItem(), current_command[ 2 ] ); fi; end, @Arguments := function() CurrentOrNewManItem(); + if IsBound( CurrentItem()!.item_type ) and CurrentItem()!.item_type = "Var" then + CurrentItem()!.item_type := "Func"; + elif not IsBound( CurrentItem()!.item_type ) then + CurrentItem()!.declareglobalname_is_function := true; + fi; CurrentItem()!.arguments := current_command[ 2 ]; end, @ItemType := function() diff --git a/tst/errorwithpos.tst b/tst/errorwithpos.tst index db3ad552..7bbff9a9 100644 --- a/tst/errorwithpos.tst +++ b/tst/errorwithpos.tst @@ -89,7 +89,7 @@ gap> ParseFixture( "tst/errorwithpos/installmethod-unterminated-arguments.g" ); Error, unterminated argument list in InstallMethod declaration, at tst/errorwithpos/installmethod-unterminated-arguments.g:4 gap> ParseFixture( "tst/errorwithpos/itemtype-unknown.g" ); -Error, unknown @ItemType Method; expected one of Func, Oper, Attr, Prop, +Error, unknown @ItemType Method; expected one of Func, Oper, Attr, Prop, Var, at tst/errorwithpos/itemtype-unknown.g:3 # diff --git a/tst/manual.expected/_Chapter_Comments.xml b/tst/manual.expected/_Chapter_Comments.xml index e61280ba..238d55b0 100644 --- a/tst/manual.expected/_Chapter_Comments.xml +++ b/tst/manual.expected/_Chapter_Comments.xml @@ -91,6 +91,11 @@ square brackets for the optional arguments, like grp[, elm] or xx[y[z] ]. If &GAP; options are used, this can be followed by a colon : and one or more assignments, like n[, r]: tries := 100.

+For DeclareGlobalName, using @Arguments or @Returns also +makes &AutoDoc; document the item as a function. This is useful because +DeclareGlobalName itself does not reveal whether the name denotes a +function or a variable. +

@@ -100,7 +105,7 @@ and one or more assignments, like n[, r]: tries := 100. @ItemType kind Overrides the kind of manual item created for the following declaration or installed method. The supported values are Func, Oper, -Attr, and Prop. +Attr, Prop, and Var.

This is mainly useful for InstallMethod. For a declaration such as DeclareAttribute or DeclareProperty, &AutoDoc; already knows the @@ -109,6 +114,12 @@ especially with one argument, the source code alone does not reliably tell whether the method belongs to an operation, an attribute, a property, or even a plain function. Without an override, such entries default to Oper.

+It is also useful for DeclareGlobalName, because that declaration can +refer to either a function or a variable. &AutoDoc; defaults such entries to +Var, but switches to Func as soon as @Arguments or +@Returns indicates function-style documentation. You can still use +@ItemType to override this explicitly. +

For example:

item!.tester_names; gap> item!.arguments; "x,y" +# +# AutoDoc_Parser_ReadFiles: DeclareGlobalName defaults and overrides +# +gap> tmpdir := Filename(DirectoryTemporary(), "autodoc-globalname-test");; +gap> if IsDirectoryPath(tmpdir) then RemoveDirectoryRecursively(tmpdir); fi; +gap> AUTODOC_CreateDirIfMissing(tmpdir); +true +gap> tmpdir_obj := Directory(tmpdir);; +gap> file := Filename(tmpdir_obj, "globalname.gd");; +gap> stream := OutputTextFile(file, false);; +gap> AppendTo(stream, "#! @Chapter Parser\n");; +gap> AppendTo(stream, "#! @Section GlobalName\n");; +gap> AppendTo(stream, "#! @Description\n");; +gap> AppendTo(stream, "DeclareGlobalName( \"DefaultGlobalName\" );\n");; +gap> AppendTo(stream, "#! @Description\n");; +gap> AppendTo(stream, "#! @Arguments x\n");; +gap> AppendTo(stream, "DeclareGlobalName( \"ArgumentGlobalName\" );\n");; +gap> AppendTo(stream, "#! @Description\n");; +gap> AppendTo(stream, "#! @Returns a value\n");; +gap> AppendTo(stream, "DeclareGlobalName( \"ReturnGlobalName\" );\n");; +gap> AppendTo(stream, "#! @Description\n");; +gap> AppendTo(stream, "#! @ItemType Var\n");; +gap> AppendTo(stream, "DeclareGlobalName( \"VariableGlobalName\" );\n");; +gap> CloseStream(stream); +gap> tree := DocumentationTree();; +gap> AutoDoc_Parser_ReadFiles( [ file ], tree, rec() ); +gap> section := SectionInTree( tree, "Parser", "GlobalName" );; +gap> section!.content[ 1 ]!.item_type; +"Var" +gap> section!.content[ 1 ]!.arguments = fail; +true +gap> section!.content[ 2 ]!.item_type; +"Func" +gap> section!.content[ 2 ]!.arguments; +"x" +gap> section!.content[ 3 ]!.item_type; +"Func" +gap> section!.content[ 3 ]!.arguments; +"arg" +gap> section!.content[ 4 ]!.item_type; +"Var" +gap> section!.content[ 4 ]!.arguments = fail; +true +gap> RemoveDirectoryRecursively(tmpdir); +true + # # warn about defined-but-never-inserted chunks # diff --git a/tst/worksheets/general.expected/_Chapter_SomeChapter.xml b/tst/worksheets/general.expected/_Chapter_SomeChapter.xml index 9feef973..3dc96a40 100644 --- a/tst/worksheets/general.expected/_Chapter_SomeChapter.xml +++ b/tst/worksheets/general.expected/_Chapter_SomeChapter.xml @@ -202,7 +202,14 @@ This text will only appear in the HTML version and the text version. - A global name + A global name documented as a variable by default + + + + + + + A global name documented as a function once arguments are given diff --git a/tst/worksheets/general.sheet/worksheet.g b/tst/worksheets/general.sheet/worksheet.g index 042d0fe4..42adcc8f 100644 --- a/tst/worksheets/general.sheet/worksheet.g +++ b/tst/worksheets/general.sheet/worksheet.g @@ -135,9 +135,14 @@ DeclareGlobalFunction( "SomeGlobalFunction" ); DeclareGlobalVariable( "SomeGlobalVariable" ); #! @Description -#! A global name +#! A global name documented as a variable by default DeclareGlobalName( "SomeGlobalName" ); +#! @Description +#! A global name documented as a function once arguments are given +#! @Arguments x +DeclareGlobalName( "SomeGlobalNameFunction" ); + #! @Description #! A filter DeclareFilter( "SomeFilter" );