Index: tests/doc.test =================================================================== diff -u -N -r8046b1da6bc0689f73d4dbdc3f8d1e03fd23acaf -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa --- tests/doc.test (.../doc.test) (revision 8046b1da6bc0689f73d4dbdc3f8d1e03fd23acaf) +++ tests/doc.test (.../doc.test) (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -82,1254 +82,1258 @@ set blocks {1 {{ @package o} { 1 2 3}} 5 {{ @object o} { 1 2 3} {} { 345} { @tag1 part1} { @tag2 part2}} 17 {{ @object o # ####} { 1 2 3} {} { 345} { @tag1 part1} { @tag2 part2}}} ? [list ::lcompare [processor comment_blocks $script] $blocks] 1 -} - -Test case parsing { - # - # TODO: Add tests for doc-parsing state machine. - # - set block { - {@command ::cc} } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 + Test case parsing { + # + # TODO: Add tests for doc-parsing state machine. + # + set block { + {@command ::cc} + } - set block { - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 0 - ? [list $cbp status ? STYLEVIOLATION] 1 - - # - # For now, a valid comment block must start with a non-space line - # (i.e., a tag or text line, depending on the section: context - # vs. description) - # - - set block { - {} - {@command ::cc} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + set block { + {} + } - set block { - {command ::cc} - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 0 + ? [list $cbp status ? STYLEVIOLATION] 1 + + # + # For now, a valid comment block must start with a non-space line + # (i.e., a tag or text line, depending on the section: context + # vs. description) + # + + set block { + {} + {@command ::cc} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + set block { + {command ::cc} + {} + } - set block { - {@command ::cc} - {some description} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - set block { - {@command ::cc} - {} - {} - {} - {@see ::o} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 - ? [list $cbp status ? COMPLETED] 1 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set block { - {@command ::cc} - {} - {some description} - {some description2} - {} - {} - } + set block { + {@command ::cc} + {some description} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + set block { + {@command ::cc} + {} + {} + {} + {@see ::o} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 + ? [list $cbp status ? COMPLETED] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set block { + {@command ::cc} + {} + {some description} + {some description2} + {} + {} + } - # Note: We do allow description blocks with intermediate space - # lines, for now. - set block { - {@command ::cc} - {} - {some description} - {some description2} - {} - {an erroreneous description line, for now} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - # - # TODO: Do not enforce space line between the context and immediate - # part block (when description is skipped)? - # - # OR: For absolutely object::qualifying parts (e.g., outside of an initcmd block), - # do we need sequences of _two_ (or more) tag lines, e.g. - # - # -- - # @object Foo - # @param attr1 - # -- - # - # THEN, we can only discriminate between the context and an - # immediate part section by requiring a space line! - # - # Alternatively, we can use the @see like syntax for object::qualifying: - # @param ::Foo#attr1 (I have a preference for this option). - set block { - {@command ::cc} - {@see someOtherEntity} - } + # Note: We do allow description blocks with intermediate space + # lines, for now. + set block { + {@command ::cc} + {} + {some description} + {some description2} + {} + {an erroreneous description line, for now} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - + # + # TODO: Do not enforce space line between the context and immediate + # part block (when description is skipped)? + # + # OR: For absolutely object::qualifying parts (e.g., outside of an initcmd block), + # do we need sequences of _two_ (or more) tag lines, e.g. + # + # -- + # @object Foo + # @param attr1 + # -- + # + # THEN, we can only discriminate between the context and an + # immediate part section by requiring a space line! + # + # Alternatively, we can use the @see like syntax for object::qualifying: + # @param ::Foo#attr1 (I have a preference for this option). + set block { + {@command ::cc} + {@see someOtherEntity} + } - # - # TODO: Disallow space lines between parts? Check back with Javadoc spec. - # - set block { - {@command ::cc} - {} - {@see SomeOtherEntity} - {add a line of description} - {} - {} - {@see SomeOtherEntity2} - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + # + # TODO: Disallow space lines between parts? Check back with Javadoc spec. + # + set block { + {@command ::cc} + {} + {@see SomeOtherEntity} + {add a line of description} + {} + {} + {@see SomeOtherEntity2} + {} + } - # - # TODO: Should we enforce a mandatory space line between description and part block? - # - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {a third line of description} - {@see entity3} - {@see SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + # + # TODO: Should we enforce a mandatory space line between description and part block? + # + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {a third line of description} + {@see entity3} + {@see SomeOtherEntity2} + } - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {a third line of description} - {} - {@see SomeOtherEntity2} - {} - {} - {an erroreneous description line, for now} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {} - {a third line of description} - {} - {@see SomeOtherEntity2} - } + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {a third line of description} + {} + {@see SomeOtherEntity2} + {} + {} + {an erroreneous description line, for now} + } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {} + {a third line of description} + {} + {@see SomeOtherEntity2} + } - set block { - {@object ::cc} - {} - {add a line of description} - {a second line of description} - {} - {@see SomeOtherEntity2} - {@xyz SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 + set block { + {@object ::cc} + {} + {add a line of description} + {a second line of description} + {} + {@see SomeOtherEntity2} + {@xyz SomeOtherEntity2} + } - set block { - {@class ::cc} - {} - {add a line of description} - {a second line of description} - {} - {@see SomeOtherEntity2} - {@xyz SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 + set block { + {@class ::cc} + {} + {add a line of description} + {a second line of description} + {} + {@see SomeOtherEntity2} + {@xyz SomeOtherEntity2} + } - # - # testing the doc object construction - # - set block { - {@object ::o} - {} - {some more text} - {and another line for the description} - {} - {@author stefan.sobernig@wu.ac.at} - {@author gustaf.neumann@wu-wien.ac.at} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity @author] "stefan.sobernig@wu.ac.at gustaf.neumann@wu-wien.ac.at"; - ? [list $entity as_text] "some more text and another line for the description"; - - set block { - {@command ::c} - {} - {some text on the command} - {} - {@see ::o} - } + # + # testing the doc object construction + # + set block { + {@object ::o} + {} + {some more text} + {and another line for the description} + {} + {@author stefan.sobernig@wu.ac.at} + {@author gustaf.neumann@wu-wien.ac.at} + } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity @author] "stefan.sobernig@wu.ac.at gustaf.neumann@wu-wien.ac.at"; + ? [list $entity as_text] "some more text and another line for the description"; + + set block { + {@command ::c} + {} + {some text on the command} + {} + {@see ::o} + } - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@command] 1 - ? [list $entity as_text] "some text on the command"; - ? [list $entity @see] "::o"; + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] - set block { - {@class ::C} - {} - {some text on the class entity} - {} - {@class-property attr1 Here! we check whether we can get a valid description block} - {for text spanning multiple lines} - } + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@command] 1 + ? [list $entity as_text] "some text on the command"; + ? [list $entity @see] "::o"; - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] + set block { + {@class ::C} + {} + {some text on the class entity} + {} + {@class-property attr1 Here! we check whether we can get a valid description block} + {for text spanning multiple lines} + } - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "some text on the class entity"; - ? [list llength [$entity @property]] 1 - ? [list [$entity @property] info has type ::nx::doc::@param] 1 - ? [list [$entity @property] as_text] "Here! we check whether we can get a valid description block for text spanning multiple lines" + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] -} + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "some text on the class entity"; + ? [list llength [$entity @property]] 1 + ? [list [$entity @property] info has type ::nx::doc::@param] 1 + ? [list [$entity @property] as_text] "Here! we check whether we can get a valid description block for text spanning multiple lines" -Test case in-situ-basics { - # - # basic test for in-situ documentation (initcmd block) - # - # - set script { - package req nx - namespace import -force ::nx::Class - Class create ::Foo { - # The class Foo defines the behaviour for all Foo objects + } + + Test case in-situ-basics { # - # @author gustaf.neumann@wu-wien.ac.at - # @author ssoberni@wu.ac.at - - # @.property attr1 + # basic test for in-situ documentation (initcmd block) + # # - # This property 1 is wonderful - # - # @see ::nx::VariableSlot - # @see ::nx::MetaSlot - :property attr1 - :property attr2 - :property attr3 + set script { + package req nx + namespace import -force ::nx::Class + Class create ::Foo { + # The class Foo defines the behaviour for all Foo objects + # + # @author gustaf.neumann@wu-wien.ac.at + # @author ssoberni@wu.ac.at + + # @.property attr1 + # + # This property 1 is wonderful + # + # @see ::nx::VariableSlot + # @see ::nx::MetaSlot + :property attr1 + :property attr2 + :property attr3 + + # @.method foo + # + # This describes the foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + :method foo {a b} {;} + } + } - # @.method foo - # - # This describes the foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - :method foo {a b} {;} + set prj [processor process -sandboxed -type eval $script] + + set entity [@class id ::Foo] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The class Foo defines the behaviour for all Foo objects"; + ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" + # TODO: Fix the [@param id] programming scheme to allow (a) for + # entities to be passed and the (b) documented structures + set entity [@property id [@class id ::Foo] class attr1] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; + + set entity [@method id ::Foo class foo] + ? [list [@class id ::Foo] @method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the foo method"; + + foreach p [$entity @parameter] expected { + "Provides a first value" + "Provides a second value" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; + } + + $prj destroy } - } - - set prj [processor process -sandboxed -type eval $script] - - set entity [@class id ::Foo] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The class Foo defines the behaviour for all Foo objects"; - ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - # TODO: Fix the [@param id] programming scheme to allow (a) for - # entities to be passed and the (b) documented structures - set entity [@property id [@class id ::Foo] class attr1] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; - - set entity [@method id ::Foo class foo] - ? [list [@class id ::Foo] @method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the foo method"; - - foreach p [$entity @parameter] expected { - "Provides a first value" - "Provides a second value" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - $prj destroy -} -# TODO: how to realise scanning and parsing for mixed ex- and -# in-situ documentation? That is, how to differentiate between -# absolutely and relatively qualified comment blocks in line-based -# scanning phase (or later)? + # TODO: how to realise scanning and parsing for mixed ex- and + # in-situ documentation? That is, how to differentiate between + # absolutely and relatively qualified comment blocks in line-based + # scanning phase (or later)? -Test case mixed-mode-parsing { - - set script { - package req nx - namespace import -force ::nx::* - # @class ::Bar - # - # The class Bar defines the behaviour for all Bar objects - # - # @author gustaf.neumann@wu-wien.ac.at - # @author ssoberni@wu.ac.at - - # @class.property {::Bar attr1} - # - # This property 1 is wonderful - # - # @see ::nx::VariableSlot - # @see ::nx::MetaSlot - - # @class.class-method {::Bar foo} - # - # - # This describes the foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - # @class.object-method {::Bar foo} - # - # This describes the per-object foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - namespace eval ::ns1 { - ::nx::Object create ooo - } - Class create Bar { + Test case mixed-mode-parsing { - :property attr1 - :property attr2 - :property attr3 + set script { + package req nx + namespace import -force ::nx::* + # @class ::Bar + # + # The class Bar defines the behaviour for all Bar objects + # + # @author gustaf.neumann@wu-wien.ac.at + # @author ssoberni@wu.ac.at - # @.method foo - # - # This describes the foo method in the initcmd - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - :public method foo {a b} { - # This describes the foo method in the method body + # @class.property {::Bar attr1} # - # @parameter a Provides a first value (refined) + # This property 1 is wonderful + # + # @see ::nx::VariableSlot + # @see ::nx::MetaSlot - } - - :public class method foo {a b c} { - # This describes the per-object foo method in the method body + # @class.class-method {::Bar foo} # - # @parameter b Provides a second value (refined) - # @parameter c Provides a third value (first time) + # + # This describes the foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + # @class.object-method {::Bar foo} + # + # This describes the per-object foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + + namespace eval ::ns1 { + ::nx::Object create ooo + } + Class create Bar { + + :property attr1 + :property attr2 + :property attr3 + + # @.method foo + # + # This describes the foo method in the initcmd + # + # @parameter a Provides a first value + # @parameter b Provides a second value + + :public method foo {a b} { + # This describes the foo method in the method body + # + # @parameter a Provides a first value (refined) + + } + + :public class method foo {a b c} { + # This describes the per-object foo method in the method body + # + # @parameter b Provides a second value (refined) + # @parameter c Provides a third value (first time) + + } + + } } - } - } - - set prj [processor process -sandboxed -type eval $script] - set entity [@class id ::Bar] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The class Bar defines the behaviour for all Bar objects"; - ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - - # TODO: Fix the [@param id] programming scheme to allow (a) for - # entities to be passed and the (b) documented structures - set entity [@property id [@class id ::Bar] class attr1] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; - - set entity [@method id ::Bar class foo] - ? [list [@class id ::Bar] @method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the foo method in the method body"; - - foreach p [$entity @parameter] expected { - "Provides a first value (refined)" - "Provides a second value" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - - set entity [@method id ::Bar object foo] - ? [list [@class id ::Bar] @class-object-method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the per-object foo method in the method body"; - - foreach p [$entity @parameter] expected { - "Provides a first value" - "Provides a second value (refined)" - "Provides a third value (first time)" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - $prj destroy -} - -Test case tag-notations-basics { - - # - # Some tests on structured/navigatable tag notations - # - - # adding support for parsing levels - - # -- @class.object.object {::D o1 o2} - set block { - {@..object o2 We have a tag notation sensitive to the parsing level} - } - - set entity [[@ @class ::D] @object o1] - set cbp [CommentBlockParser process -parsing_level 1 -partof_entity $entity $block] - ? [list $cbp status ? LEVELMISMATCH] 1 - set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "We have a tag notation sensitive to the parsing level" - - set block { - {@..object {o2 o3} We still look for balanced specs} - } - - set entity [[@ @class ::D] @object o1] - set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - # This fails because we do not allow uninitialised/non-existing - # entity objects (@object o) along the resolution path ... - set block { - {@class.object.property {::C o attr1} We have an invalid specification} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 - # ? [list $cbp message] "The tag 'object' is not supported for the entity type '@class'" - - set block { - {@class.method.property attr1 We have an imbalanced specification (the names are underspecified!)} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - ? [list $cbp message] "Imbalanced tag line spec: 'class method property' vs. 'attr1'" - - # For now, we do not verify and use a fixed scope of permissive tag - # names. So, punctuation errors or typos are most probably reported - # as imbalanced specs. In the mid-term run, this should rather - # become an INVALIDTAG condition. - set block { - {@cla.ss.method.parameter {::C foo p1} We mistyped a tag fragment} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - ? [list $cbp message] "Imbalanced tag line spec: 'cla ss method parameter' vs. '::C foo p1'" - - set block { - {@cla,ss.method.parameter {::C foo p1} We mistyped a tag fragment} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 - ? [list $cbp message] "The entity type '@cla,ss' is not available." -} - -Test case tag-notations-extended { - set script { - # @class ::C - # - # The global description of ::C - # - # @property attr1 Here we can only provide a description block for object parameters - - # @class.object-method {::C sub} - # - # For now, we have to declare a family of sub methods explicitly - # (allows for providing some overview, shared description) - - - # @class.property {::C attr1} Here, we could also write '@class.class-property \{::C attr1\}', @property is a mere forwarder! In the context section, only one-liners are allowed! - - # @class.object.property {::C foo p1} A short description is ... - # - # .. is overruled by a long one ... - - # If addressing to a nested object, one strategy would be to use - # @object and provide the object identifier (which reflects the - # nesting, e.g. ::C::foo). However, we cannot distinguish between - # namespace qualifiers denoting an object, class or owning - # namespace! - # - # ISSUE: If specifying an axis ".object", we would have to define - # a part property @object on @class and @object. However, @object - # would be ambiguous now: It could be called in a freestanding - # (absolute) manner AND in a contextualised manner (in an initcmd - # script). In the latter case, it would fail because we would have - # to provide a FQ'ed name (which defeats the purpose of a nested = - # contextualised notation). - # - # SO: for now, we introduce a part property child-object (and - # child-class?) to discrimate between the two situations ... - # - # TODO: How to register this so created @object entity as nested - # object with the doc entity represented the parent object? - - Class create C { - # This is the initcmd-level description of ::C which overwrites the - # global description (see above) + set prj [processor process -sandboxed -type eval $script] + set entity [@class id ::Bar] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The class Bar defines the behaviour for all Bar objects"; + ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - # @.property attr1 - # - # This is equivalent to writing "@class-property attr1" - :property attr1 { - # This description does not apply to the object parameter - # "attr1" owned by the ::C class, rather it is a description - # of the property slot object! How should we deal with this - # situation? Should this level overwrite the top-level and - # initcmd-level descriptions? + # TODO: Fix the [@param id] programming scheme to allow (a) for + # entities to be passed and the (b) documented structures + set entity [@property id [@class id ::Bar] class attr1] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; + + set entity [@method id ::Bar class foo] + ? [list [@class id ::Bar] @method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the foo method in the method body"; + + foreach p [$entity @parameter] expected { + "Provides a first value (refined)" + "Provides a second value" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; } - # @.class-object-property attr2 Carries a short desc only - :class property attr2 - # @.method foo - # - # @parameter p1 - set fooHandle [:public method foo {p1} { - # Here goes some method-body-level description - # - # @parameter p1 The most specific level! - return [current method]-$p1-[current] - }] + set entity [@method id ::Bar object foo] + ? [list [@class id ::Bar] @class-object-method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the per-object foo method in the method body"; - # @.object-method bar - # - # Before referring to its parts, an entity must exist; so - # declare eagerly ... + foreach p [$entity @parameter] expected { + "Provides a first value" + "Provides a second value (refined)" + "Provides a third value (first time)" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; + } + + $prj destroy + } - # @.class-object-method.parameter {bar p1} + Test case tag-notations-basics { + # - # This extended form allows to describe a method parameter with all - # its structural features! - set barHandle [:public class method bar {p1} { - return [current method]-$p1-[current] - }] + # Some tests on structured/navigatable tag notations + # - # @.object foo 'foo' needs to be defined before referencing any of its parts! + # adding support for parsing levels - # @.object.property {foo p1} - # - # The first element in the name list is resolved into a fully - # qualified (absolute) entity, based on the object owning the - # initcmd! - Object create [current]::foo { - # Adding a line for the first time (not processed in the initcmd phase!) - - # @..property p1 - # - # This is equivalent to stating "@class-object-property p1" - :property p1 + # -- @class.object.object {::D o1 o2} + set block { + {@..object o2 We have a tag notation sensitive to the parsing level} } - # @.class Foo X - # - # By providing a fully-qualified identifier ("::Foo") you leave the - # context of the initcmd-owning object, i.e. you would NOT refer to - # a nested class object named "Foo" anymore! + set entity [[@ @class ::D] @object o1] + set cbp [CommentBlockParser process -parsing_level 1 -partof_entity $entity $block] + ? [list $cbp status ? LEVELMISMATCH] 1 + set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "We have a tag notation sensitive to the parsing level" - # @.class.property {Foo p1} - # - # This is equivalent to stating "@child-class.class-property {Foo p1}" + set block { + {@..object {o2 o3} We still look for balanced specs} + } - # @.class.class-object-property {Foo p2} Y - Class create [current]::Foo { + set entity [[@ @class ::D] @object o1] + set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + # This fails because we do not allow uninitialised/non-existing + # entity objects (@object o) along the resolution path ... + set block { + {@class.object.property {::C o attr1} We have an invalid specification} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 + # ? [list $cbp message] "The tag 'object' is not supported for the entity type '@class'" + + set block { + {@class.method.property attr1 We have an imbalanced specification (the names are underspecified!)} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + ? [list $cbp message] "Imbalanced tag line spec: 'class method property' vs. 'attr1'" + + # For now, we do not verify and use a fixed scope of permissive tag + # names. So, punctuation errors or typos are most probably reported + # as imbalanced specs. In the mid-term run, this should rather + # become an INVALIDTAG condition. + set block { + {@cla.ss.method.parameter {::C foo p1} We mistyped a tag fragment} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + ? [list $cbp message] "Imbalanced tag line spec: 'cla ss method parameter' vs. '::C foo p1'" + + set block { + {@cla,ss.method.parameter {::C foo p1} We mistyped a tag fragment} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 + ? [list $cbp message] "The entity type '@cla,ss' is not available." + } + + Test case tag-notations-extended { + set script { + # @class ::C + # + # The global description of ::C + # + # @property attr1 Here we can only provide a description block for object parameters - # @..property p1 + # @class.object-method {::C sub} + # + # For now, we have to declare a family of sub methods explicitly + # (allows for providing some overview, shared description) + + + # @class.property {::C attr1} Here, we could also write '@class.class-property \{::C attr1\}', @property is a mere forwarder! In the context section, only one-liners are allowed! + + # @class.object.property {::C foo p1} A short description is ... + # + # .. is overruled by a long one ... + + # If addressing to a nested object, one strategy would be to use + # @object and provide the object identifier (which reflects the + # nesting, e.g. ::C::foo). However, we cannot distinguish between + # namespace qualifiers denoting an object, class or owning + # namespace! + # + # ISSUE: If specifying an axis ".object", we would have to define + # a part property @object on @class and @object. However, @object + # would be ambiguous now: It could be called in a freestanding + # (absolute) manner AND in a contextualised manner (in an initcmd + # script). In the latter case, it would fail because we would have + # to provide a FQ'ed name (which defeats the purpose of a nested = + # contextualised notation). # + # SO: for now, we introduce a part property child-object (and + # child-class?) to discrimate between the two situations ... # - # This is equivalent to stating "@class-property p1"; or - # '@class.object.property {::C Foo p1}' from the top-level. - :property p1 + # TODO: How to register this so created @object entity as nested + # object with the doc entity represented the parent object? - # @..class-object-property p2 - :class property p2 + Class create C { + # This is the initcmd-level description of ::C which overwrites the + # global description (see above) + + # @.property attr1 + # + # This is equivalent to writing "@class-property attr1" + :property attr1 { + # This description does not apply to the object parameter + # "attr1" owned by the ::C class, rather it is a description + # of the property slot object! How should we deal with this + # situation? Should this level overwrite the top-level and + # initcmd-level descriptions? + } + + # @.class-object-property attr2 Carries a short desc only + :class property attr2 + + # @.method foo + # + # @parameter p1 + set fooHandle [:public method foo {p1} { + # Here goes some method-body-level description + # + # @parameter p1 The most specific level! + return [current method]-$p1-[current] + }] + + # @.object-method bar + # + # Before referring to its parts, an entity must exist; so + # declare eagerly ... + + # @.class-object-method.parameter {bar p1} + # + # This extended form allows to describe a method parameter with all + # its structural features! + set barHandle [:public class method bar {p1} { + return [current method]-$p1-[current] + }] + + # @.object foo 'foo' needs to be defined before referencing any of its parts! + + # @.object.property {foo p1} + # + # The first element in the name list is resolved into a fully + # qualified (absolute) entity, based on the object owning the + # initcmd! + Object create [current]::foo { + # Adding a line for the first time (not processed in the initcmd phase!) + + # @..property p1 + # + # This is equivalent to stating "@class-object-property p1" + :property p1 + } + + # @.class Foo X + # + # By providing a fully-qualified identifier ("::Foo") you leave the + # context of the initcmd-owning object, i.e. you would NOT refer to + # a nested class object named "Foo" anymore! + + # @.class.property {Foo p1} + # + # This is equivalent to stating "@child-class.class-property {Foo p1}" + + # @.class.class-object-property {Foo p2} Y + Class create [current]::Foo { + + # @..property p1 + # + # + # This is equivalent to stating "@class-property p1"; or + # '@class.object.property {::C Foo p1}' from the top-level. + :property p1 + + # @..class-object-property p2 + :class property p2 + } + + + # @.class-object-method.sub-method {sub foo} + # + # ISSUE: Should submethods be navigatable through "method" (i.e., + # "@method.method.method ...") or "submethod" (i.e., + # "@method.submethod.submethod ...")? ISSUE: Should it be sub* with + # "-" (to correspond to "@class-object-method", "@class-method")? Also, we + # could allow both (@sub-method is the property name, @method is a + # forwarder in the context of an owning @method object!) + # + # @parameter p1 Some words on p1 + :class alias "sub foo" $fooHandle + + # @.method sub + # + # The desc of the ensemble object 'sub' + # + # @sub-method bar Only description available here ... + + # ISSUE: Should the helper object "sub" be documentable in its own + # right? This would be feasible with the dotted notation from + # within and outside the initcmd script block, e.g. "@object sub" or + # "@class.object {::C sub}" + # + # ISSUE: Is it correct to say the sub appears as per-object method + # and so do its submethods? Or is it misleading to document it that + # way? Having an "@class-object-submethod" would not make much sense to + # me?! + :alias "sub bar" $barHandle + + # @.class-object-method sub A brief desc + + # @.class-object-method {"sub foo2"} + # + # could allow both (@sub-method is the property name, @method is a + # forwarder in the context of an owning @method object!) + # + # @parameter p1 Some words on p1 + # @see anotherentity + # @author ss@thinkersfoot.net + :class alias "sub foo2" $fooHandle + } } - - # @.class-object-method.sub-method {sub foo} # - # ISSUE: Should submethods be navigatable through "method" (i.e., - # "@method.method.method ...") or "submethod" (i.e., - # "@method.submethod.submethod ...")? ISSUE: Should it be sub* with - # "-" (to correspond to "@class-object-method", "@class-method")? Also, we - # could allow both (@sub-method is the property name, @method is a - # forwarder in the context of an owning @method object!) - # - # @parameter p1 Some words on p1 - :class alias "sub foo" $fooHandle + # 1) process the top-level comments (PARSING LEVEL 0) + # - # @.method sub + processor readin $script + + + # --testing-- "@class ::C" + set entity [@class id ::C] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The global description of ::C"; + # --testing-- "@class.property {::C attr1}" + set entity [@property id $entity class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "Here, we could also write '@class.class-property {::C attr1}', @property is a mere forwarder! In the context section, only one-liners are allowed!" + + # --testing-- "@class.object.property {::C foo p1} A short description is ..." + # set entity [@property id $entity class attr1] + # set entity [@object id -partof_name ::C -scope child foo] + # ? [list ::nsf::object::exists $entity] 1 + # ? [list $entity info has type ::nx::doc::@object] 1 + # ? [list $entity as_text] "" + # set entity [@property id $entity object p1] + # ? [list ::nsf::object::exists $entity] 1 + # ? [list $entity info has type ::nx::doc::@property] 1 + # ? [list $entity as_text] ".. is overruled by a long one ..." + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $entity class p1] + ? [list ::nsf::object::exists $entity] 0 + # ? [list $entity info has type ::nx::doc::@property] 1 + # ? [list $entity as_text] ".. is overruled by a long one ..." + + # --testing-- @class-object-property attr2 (its non-existance) + set entity [@property id [@class id ::C] object attr2] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-class Foo (its non-existance) + set entity [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 0 + # --testing -- @method foo (its non-existance) + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @class-object-method.parameter {bar p1} (its non-existance) + set entity [@parameter id [@method id ::C class bar] "" p1] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-object.property {foo p1} (its non-existance) + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 0 + # - # The desc of the ensemble object 'sub' + # 2) process the initcmd comments (PARSING LEVEL 1) # - # @sub-method bar Only description available here ... - # ISSUE: Should the helper object "sub" be documentable in its own - # right? This would be feasible with the dotted notation from - # within and outside the initcmd script block, e.g. "@object sub" or - # "@class.object {::C sub}" + puts stderr -----INITCMD------ + ::nsf::configure keepinitcmd true + eval $script + ::nsf::configure keepinitcmd false + lassign [processor readin \ + -parsing_level 1 \ + -docstring \ + -tag @class \ + -name ::C \ + [::C eval {set :__initcmd}]] _ processed_entities + # a) existing, but modified ... + + set entity [@class id ::C] + ? $_ $entity + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "This is the initcmd-level description of ::C which overwrites the global description (see above)" + + set entity [@property id $entity class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This is equivalent to writing "@class-property attr1"} + + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "'foo' needs to be defined before referencing any of its parts!"; # still empty! + set entity [@property id $entity object p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "The first element in the name list is resolved into a fully qualified (absolute) entity, based on the object owning the initcmd!" + + # b) newly added ... + + # --testing-- @class-object-property attr2 + set entity [@property id [@class id ::C] object attr2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "Carries a short desc only"; + + # --testing-- @child-class Foo + # TODO: provide a check against fully-qualified names in part specifications + set entity [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] {By providing a fully-qualified identifier ("::Foo") you leave the context of the initcmd-owning object, i.e. you would NOT refer to a nested class object named "Foo" anymore!} + + set entity [@property id [@class id ::C] class p1] + ? [list ::nsf::object::exists $entity] 0; # should be 0 at this stage! + + # --testing -- @method foo + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "" + # --testing-- @class-object-method.parameter {bar p1} (its non-existance) It + # still cannot exist as a documented entity, as the class method + # has not been initialised before! + set entity [@parameter id [@method id ::C class bar] "" p1] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-class.property {foo p1} (its non-existance) + # --testing-- @child-class.object-property {foo p2} (its non-existance) + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $cl] 1 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] {This is equivalent to stating "@child-class.class-property {Foo p1}"} + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Y" + + set entity [@method id ::C class sub] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "The desc of the ensemble object 'sub'" + + set entity [@method id ::C class sub::bar] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Only description available here ..." + + set entity [@method id ::C object sub] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "A brief desc" + + set entity [@method id ::C object sub::foo2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "could allow both (@sub-method is the property name, @method is a forwarder in the context of an owning @method object!)" + ? [list $entity @see] "anotherentity" + # TODO: @author not supported for @method (fine so?) + # ? [list $entity @author] "ss@thinkersfoot" + set entity [@parameter id $entity "" p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Some words on p1" + # - # ISSUE: Is it correct to say the sub appears as per-object method - # and so do its submethods? Or is it misleading to document it that - # way? Having an "@class-object-submethod" would not make much sense to - # me?! - :alias "sub bar" $barHandle + # 3a) process the property initcmds and method bodies (PARSING LEVEL 2)! + # - # @.class-object-method sub A brief desc + set project [@project new -name "_%@"] + $project sandbox [Sandbox new] + processor process=@class $project [@class id ::C] - # @.class-object-method {"sub foo2"} + # methods ... + + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Here goes some method-body-level description" + set entity [@parameter id [@method id ::C class foo] "" p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "The most specific level!" + + # attributes ... + + # attr1 + set entity [@property id [@class id ::C] class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This description does not apply to the object parameter "attr1" owned by the ::C class, rather it is a description of the property slot object! How should we deal with this situation? Should this level overwrite the top-level and initcmd-level descriptions?} + # - # could allow both (@sub-method is the property name, @method is a - # forwarder in the context of an owning @method object!) + # 3b) nested objects/ classes (PARSING LEVEL 2)! # - # @parameter p1 Some words on p1 - # @see anotherentity - # @author ss@thinkersfoot.net - :class alias "sub foo2" $fooHandle - } - } - - # - # 1) process the top-level comments (PARSING LEVEL 0) - # - - processor readin $script - - - # --testing-- "@class ::C" - set entity [@class id ::C] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The global description of ::C"; - # --testing-- "@class.property {::C attr1}" - set entity [@property id $entity class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "Here, we could also write '@class.class-property {::C attr1}', @property is a mere forwarder! In the context section, only one-liners are allowed!" + processor readin \ + -docstring \ + -parsing_level 2 \ + -tag @object \ + -name ::C::foo \ + [::C::foo eval {set :__initcmd}] + + processor process=@object $project [@object id ::C::foo] + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "Adding a line for the first time (not processed in the initcmd phase!)"; # still empty! + set entity [@property id $entity object p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This is equivalent to stating "@class-object-property p1"} + + processor readin \ + -docstring \ + -parsing_level 2 \ + -tag @class \ + -name ::C::Foo \ + [::C::Foo eval {set :__initcmd}] + processor process=@class $project [@class id ::C::Foo] + + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $cl] 1 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] {This is equivalent to stating "@class-property p1"; or '@class.object.property {::C Foo p1}' from the top-level.} + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "" + + # + # basic testing of "properties" (switch attributes) + # - # --testing-- "@class.object.property {::C foo p1} A short description is ..." - # set entity [@property id $entity class attr1] - # set entity [@object id -partof_name ::C -scope child foo] - # ? [list ::nsf::object::exists $entity] 1 - # ? [list $entity info has type ::nx::doc::@object] 1 - # ? [list $entity as_text] "" - # set entity [@property id $entity object p1] - # ? [list ::nsf::object::exists $entity] 1 - # ? [list $entity info has type ::nx::doc::@property] 1 - # ? [list $entity as_text] ".. is overruled by a long one ..." + ? [list $cl eval {set :@deprecated}] 0 + ? [list $cl eval {set :@stashed}] 0 + ? [list $cl eval {set :@c-implemented}] 0 - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $entity class p1] - ? [list ::nsf::object::exists $entity] 0 - # ? [list $entity info has type ::nx::doc::@property] 1 - # ? [list $entity as_text] ".. is overruled by a long one ..." + ? [list $cl @deprecated] 1 + ? [list $cl @stashed] 1 + ? [list $cl @c-implemented] 1 - # --testing-- @class-object-property attr2 (its non-existance) - set entity [@property id [@class id ::C] object attr2] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-class Foo (its non-existance) - set entity [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 0 - # --testing -- @method foo (its non-existance) - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @class-object-method.parameter {bar p1} (its non-existance) - set entity [@parameter id [@method id ::C class bar] "" p1] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-object.property {foo p1} (its non-existance) - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 0 + ? [list $cl eval {set :@deprecated}] 1 + ? [list $cl eval {set :@stashed}] 1 + ? [list $cl eval {set :@c-implemented}] 1 - # - # 2) process the initcmd comments (PARSING LEVEL 1) - # - - puts stderr -----INITCMD------ - ::nsf::configure keepinitcmd true - eval $script - ::nsf::configure keepinitcmd false - lassign [processor readin \ - -parsing_level 1 \ - -docstring \ - -tag @class \ - -name ::C \ - [::C eval {set :__initcmd}]] _ processed_entities - # a) existing, but modified ... - - set entity [@class id ::C] - ? $_ $entity - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "This is the initcmd-level description of ::C which overwrites the global description (see above)" - - set entity [@property id $entity class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This is equivalent to writing "@class-property attr1"} - - - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "'foo' needs to be defined before referencing any of its parts!"; # still empty! - set entity [@property id $entity object p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "The first element in the name list is resolved into a fully qualified (absolute) entity, based on the object owning the initcmd!" - - # b) newly added ... - - # --testing-- @class-object-property attr2 - set entity [@property id [@class id ::C] object attr2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "Carries a short desc only"; - - # --testing-- @child-class Foo - # TODO: provide a check against fully-qualified names in part specifications - set entity [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] {By providing a fully-qualified identifier ("::Foo") you leave the context of the initcmd-owning object, i.e. you would NOT refer to a nested class object named "Foo" anymore!} - - set entity [@property id [@class id ::C] class p1] - ? [list ::nsf::object::exists $entity] 0; # should be 0 at this stage! - - # --testing -- @method foo - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "" - # --testing-- @class-object-method.parameter {bar p1} (its non-existance) It - # still cannot exist as a documented entity, as the class method - # has not been initialised before! - set entity [@parameter id [@method id ::C class bar] "" p1] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-class.property {foo p1} (its non-existance) - # --testing-- @child-class.object-property {foo p2} (its non-existance) - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $cl] 1 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] {This is equivalent to stating "@child-class.class-property {Foo p1}"} - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Y" - - set entity [@method id ::C class sub] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "The desc of the ensemble object 'sub'" - - set entity [@method id ::C class sub::bar] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Only description available here ..." - - set entity [@method id ::C object sub] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "A brief desc" - - set entity [@method id ::C object sub::foo2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "could allow both (@sub-method is the property name, @method is a forwarder in the context of an owning @method object!)" - ? [list $entity @see] "anotherentity" - # TODO: @author not supported for @method (fine so?) - # ? [list $entity @author] "ss@thinkersfoot" - set entity [@parameter id $entity "" p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Some words on p1" - - # - # 3a) process the property initcmds and method bodies (PARSING LEVEL 2)! - # - - set project [@project new -name "_%@"] - $project sandbox [Sandbox new] - processor process=@class $project [@class id ::C] - - # methods ... - - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Here goes some method-body-level description" - set entity [@parameter id [@method id ::C class foo] "" p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "The most specific level!" - - # attributes ... - - # attr1 - set entity [@property id [@class id ::C] class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This description does not apply to the object parameter "attr1" owned by the ::C class, rather it is a description of the property slot object! How should we deal with this situation? Should this level overwrite the top-level and initcmd-level descriptions?} - - # - # 3b) nested objects/ classes (PARSING LEVEL 2)! - # - processor readin \ - -docstring \ - -parsing_level 2 \ - -tag @object \ - -name ::C::foo \ - [::C::foo eval {set :__initcmd}] - - processor process=@object $project [@object id ::C::foo] - - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "Adding a line for the first time (not processed in the initcmd phase!)"; # still empty! - set entity [@property id $entity object p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This is equivalent to stating "@class-object-property p1"} - - processor readin \ - -docstring \ - -parsing_level 2 \ - -tag @class \ - -name ::C::Foo \ - [::C::Foo eval {set :__initcmd}] - processor process=@class $project [@class id ::C::Foo] - - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $cl] 1 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] {This is equivalent to stating "@class-property p1"; or '@class.object.property {::C Foo p1}' from the top-level.} - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "" - - # - # basic testing of "properties" (switch attributes) - # + set entity [@method id ::C class foo] + ? [list $entity eval {set :@syshook}] 0 + ? [list $entity @syshook] 1 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook 0] {wrong # args: should be "get obj prop"} + ? [list $entity eval {set :@syshook 0}] 0 + ? [list $entity @syshook] 1 - ? [list $cl eval {set :@deprecated}] 0 - ? [list $cl eval {set :@stashed}] 0 - ? [list $cl eval {set :@c-implemented}] 0 - ? [list $cl @deprecated] 1 - ? [list $cl @stashed] 1 - ? [list $cl @c-implemented] 1 + } - ? [list $cl eval {set :@deprecated}] 1 - ? [list $cl eval {set :@stashed}] 1 - ? [list $cl eval {set :@c-implemented}] 1 - - set entity [@method id ::C class foo] - ? [list $entity eval {set :@syshook}] 0 - ? [list $entity @syshook] 1 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook 0] {wrong # args: should be "get obj prop"} - ? [list $entity eval {set :@syshook 0}] 0 - ? [list $entity @syshook] 1 - - -} - -Test case switch-parts { - - set script { - package req nx - namespace import ::nx::* - Class create Enil { - # The class Enil defines the behaviour for all Enil objects, - # however, it is deprecated and will be removed from the - # provided doc entities in the next iteration ... - # - # @author ssoberni@wu.ac.at - # @deprecated + Test case switch-parts { - # @.property attr1 - # - # This property 1 will be invisibile in the generated doc - # - # @stashed - :property attr1 + set script { + package req nx + namespace import ::nx::* + Class create Enil { + # The class Enil defines the behaviour for all Enil objects, + # however, it is deprecated and will be removed from the + # provided doc entities in the next iteration ... + # + # @author ssoberni@wu.ac.at + # @deprecated + + # @.property attr1 + # + # This property 1 will be invisibile in the generated doc + # + # @stashed + :property attr1 + + # @.method foo + # + # This describes the foo method which is called from within the + # nx-enabled Tcl engine + # + # @syshook + :public method foo {a b} {;} + + :public method baz {} { + # This method entity sets a couple of properties in series ... + # + # @property c-implemented syshook + } + } + } - # @.method foo - # - # This describes the foo method which is called from within the - # nx-enabled Tcl engine - # - # @syshook - :public method foo {a b} {;} + set prj [processor process -sandboxed -type eval $script] + set cl [@class id ::Enil] - :public method baz {} { - # This method entity sets a couple of properties in series ... - # - # @property c-implemented syshook - } + ? [list $cl eval {set :@deprecated}] 1 + ? [list $cl @deprecated] 1 + ? [list $cl eval {set :@c-implemented}] 0 + ? [list $cl eval {set :@stashed}] 0 + ? [list $cl @author] ssoberni@wu.ac.at + + set entity [@property id $cl class attr1] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 1 + ? [list $entity @stashed] 1 + ? [list $entity eval {set :@c-implemented}] 0 + + set entity [@method id ::Enil class foo] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 0 + ? [list $entity eval {set :@c-implemented}] 0 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook] 1 + + set entity [@method id ::Enil class baz] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 0 + ? [list $entity eval {set :@c-implemented}] 1 + ? [list $entity @c-implemented] 1 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook] 1 + + } - } - - set prj [processor process -sandboxed -type eval $script] - set cl [@class id ::Enil] - - ? [list $cl eval {set :@deprecated}] 1 - ? [list $cl @deprecated] 1 - ? [list $cl eval {set :@c-implemented}] 0 - ? [list $cl eval {set :@stashed}] 0 - ? [list $cl @author] ssoberni@wu.ac.at - - set entity [@property id $cl class attr1] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 1 - ? [list $entity @stashed] 1 - ? [list $entity eval {set :@c-implemented}] 0 - - set entity [@method id ::Enil class foo] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 0 - ? [list $entity eval {set :@c-implemented}] 0 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook] 1 - - set entity [@method id ::Enil class baz] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 0 - ? [list $entity eval {set :@c-implemented}] 1 - ? [list $entity @c-implemented] 1 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook] 1 - - -} -puts stderr ================================================= + if {0} { + puts stderr ================================================= -# TODO: Figure out where to place nsf.nxd for convenient location ... + # TODO: Figure out where to place nsf.nxd for convenient location ... -puts stderr >>>>>>>NextScriptingFramework<<<<<<<< -set project [::nx::doc::@project new \ - -name NextScriptingFramework \ - -url http://www.next-scripting.org/ \ - -version 1.0.0a \ - -@namespace "::nsf" \ - -sources { - package nsf - }] + puts stderr >>>>>>>NextScriptingFramework<<<<<<<< + set project [::nx::doc::@project new \ + -name NextScriptingFramework \ + -url http://www.next-scripting.org/ \ + -version 1.0.0a \ + -@namespace "::nsf" \ + -sources { + package nsf + }] -set ::nsf::includes { - ::nsf::alias - ::nsf::configure - ::nsf::current - ::nsf::finalize - ::nsf::interp - ::nsf::is - ::nsf::log - ::nsf::my - ::nsf::next - ::nsf::relation - ::nsf::tmpdir - ::nsf::assertion - ::nsf::objectsystem::create - ::nsf::dispatch - ::nsf::var::exists - ::nsf::exithandler - ::nsf::forward - ::nsf::var::import - ::nsf::object::exists - ::nsf::method - ::nsf::method::property - ::nsf::method::provide - ::nsf::object::qualify - ::nsf::method::require - ::nsf::setter - ::nsf::var::set -} + set ::nsf::includes { + ::nsf::alias + ::nsf::configure + ::nsf::current + ::nsf::finalize + ::nsf::interp + ::nsf::is + ::nsf::log + ::nsf::my + ::nsf::next + ::nsf::relation + ::nsf::tmpdir + ::nsf::assertion + ::nsf::objectsystem::create + ::nsf::dispatch + ::nsf::var::exists + ::nsf::exithandler + ::nsf::forward + ::nsf::var::import + ::nsf::object::exists + ::nsf::method + ::nsf::method::property + ::nsf::method::provide + ::nsf::object::qualify + ::nsf::method::require + ::nsf::setter + ::nsf::var::set + } -set project [processor process \ - -sandboxed \ - -validate \ - -include $::nsf::includes $project] + set project [processor process \ + -sandboxed \ + -validate \ + -include $::nsf::includes $project] -::nx::doc::make doc \ - -format html \ - $project \ - -theme yuidoc \ - -layout many-to-many \ - -outdir [::nsf::tmpdir] + ::nx::doc::make doc \ + -format html \ + $project \ + -theme yuidoc \ + -layout many-to-many \ + -outdir [::nsf::tmpdir] -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] -puts stderr >>>>>>>NextScriptingLanguage<<<<<<<< -set ::nx::excludes { - ::nsf::parametersfromslots - ::nx::infoOptions - ::nx::isSlotContainer - ::nx::slotObj -} -# lappend ::nx::excludes {*}::nsf::classes::nx::Object::[join { -# __default_property_call_protection -# __default_method_call_protection -# __resolve_method_path -# cleanup -# defaultmethod -# init -# objectparameter -# residualargs -# uplevel -# upvar -# } " ::nsf::classes::nx::Object::"] + puts stderr >>>>>>>NextScriptingLanguage<<<<<<<< -set project [::nx::doc::@project new \ - -name NextScriptingLanguage \ - -url http://www.next-scripting.org/ \ - -version 1.0.0a \ - -@namespace "::nx" \ - -sources { - package nx - } -depends $project] + set ::nx::excludes { + ::nsf::parametersfromslots + ::nx::infoOptions + ::nx::isSlotContainer + ::nx::slotObj + } -dict set timings process [time { + # lappend ::nx::excludes {*}::nsf::classes::nx::Object::[join { + # __default_property_call_protection + # __default_method_call_protection + # __resolve_method_path + # cleanup + # defaultmethod + # init + # objectparameter + # residualargs + # uplevel + # upvar + # } " ::nsf::classes::nx::Object::"] - # ISSUE: If calling '-namespace "::nx"' instead of '-@namespace - # "::nx"', we get an irritating failure. VERIFY! - processor process \ - -validate \ - -sandboxed \ - -exclude $::nx::excludes \ - $project -} 1] + set project [::nx::doc::@project new \ + -name NextScriptingLanguage \ + -url http://www.next-scripting.org/ \ + -version 1.0.0a \ + -@namespace "::nx" \ + -sources { + package nx + } -depends $project] -dict set timings make.html.yuidoc [time { - ::nx::doc::make doc $project \ - -outdir [::nsf::tmpdir] -} 1] + dict set timings process [time { -dict set timings make.html.asciidoc [time { -::nx::doc::make doc \ - -format html \ - $project \ - -theme asciidoc \ - -layout 1-to-1 \ - -outdir [::nsf::tmpdir] -} 1] + # ISSUE: If calling '-namespace "::nx"' instead of '-@namespace + # "::nx"', we get an irritating failure. VERIFY! + processor process \ + -validate \ + -sandboxed \ + -exclude $::nx::excludes \ + $project + } 1] -dict set timings make.xowiki.yuidoc [time { -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] -} 1] + dict set timings make.html.yuidoc [time { + ::nx::doc::make doc $project \ + -outdir [::nsf::tmpdir] + } 1] -dict for {probe t} $timings { - puts stderr "\t$probe -> $t" -} + dict set timings make.html.asciidoc [time { + ::nx::doc::make doc \ + -format html \ + $project \ + -theme asciidoc \ + -layout 1-to-1 \ + -outdir [::nsf::tmpdir] + } 1] -set project [::nx::doc::@project new \ - -name XOTcl2 \ - -url http://www.xotcl.org/ \ - -version 2.0.0 \ - -@namespace "::xotcl" \ - -sources { - @package XOTcl-langRef - }] + dict set timings make.xowiki.yuidoc [time { + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] + } 1] -processor process \ - -sandboxed \ - $project + dict for {probe t} $timings { + puts stderr "\t$probe -> $t" + } -::nx::doc::make doc \ - -format html \ - $project \ - -theme yuidoc \ - -outdir [::nsf::tmpdir] + set project [::nx::doc::@project new \ + -name XOTcl2 \ + -url http://www.xotcl.org/ \ + -version 2.0.0 \ + -@namespace "::xotcl" \ + -sources { + @package XOTcl-langRef + }] -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] + processor process \ + -sandboxed \ + $project -# # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # + ::nx::doc::make doc \ + -format html \ + $project \ + -theme yuidoc \ + -outdir [::nsf::tmpdir] -# 1) Test case scoping rules -> in Object->eval() + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] -Test case issues? { + } + # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # - # TODO: where to locate the @ comments (in predefined.xotcl, in - # gentclAPI.decls)? how to deal with ::nsf::* vs. ::nx::* - - # TODO: which values are returned from Object->configure() and - # passed to init()? how to document residualargs()? + # 1) Test case scoping rules -> in Object->eval() - # TODO: Object->cleanup() said: "Resets an object or class into an - # initial state, as after construction." If by construction it means - # after create(), then cleanup() is missing a configure() call to - # set defaults, etc! - # ?? cleanup does not set defaults; depending on "softrecreate", it - # deletes instances, childobjects, procs, instprocs, ... + Test case issues? { - # TODO: what is Object->__next() for? + # TODO: where to locate the @ comments (in predefined.xotcl, in + # gentclAPI.decls)? how to deal with ::nsf::* vs. ::nx::* + + # TODO: which values are returned from Object->configure() and + # passed to init()? how to document residualargs()? - # See the following script: - # + # TODO: Object->cleanup() said: "Resets an object or class into an + # initial state, as after construction." If by construction it means + # after create(), then cleanup() is missing a configure() call to + # set defaults, etc! + # ?? cleanup does not set defaults; depending on "softrecreate", it + # deletes instances, childobjects, procs, instprocs, ... -# Object instproc defaultmethod {} {puts "[self proc]"; return [self]} -# Class A -# A instproc defaultmethod {} {puts "[self proc]"; [::xotcl::my info parent] __next} -# Class D -instproc t {} {puts "my stuff"} -# D create d1 -# puts [d1 t] -# ### we create a subobject named t, which shadows effectively D->t -# A create d1::t -# puts === -# # when we call "d1 t", we effectively call "d1::t", which calls "default method". -# # the defaultmethod should do a next on object d1. -# puts [d1 t] -# puts ===EXIT + # TODO: what is Object->__next() for? - # but seems - at least in this usecase broken. Deactivated - # in source for now. + # See the following script: + # - # TODO: why is XOTclOUplevelMethodStub/XOTclOUplevelMethod defined - # with "args" while it logically uses the stipulated parameter - # signature (level ...). is this because of the first pos, optional - # parameter? ... same goes for upvar() ... + # Object instproc defaultmethod {} {puts "[self proc]"; return [self]} + # Class A + # A instproc defaultmethod {} {puts "[self proc]"; [::xotcl::my info parent] __next} + # Class D -instproc t {} {puts "my stuff"} + # D create d1 + # puts [d1 t] + # ### we create a subobject named t, which shadows effectively D->t + # A create d1::t + # puts === + # # when we call "d1 t", we effectively call "d1::t", which calls "default method". + # # the defaultmethod should do a next on object d1. + # puts [d1 t] + # puts ===EXIT - # the logic is a tribute to the argument logic in Tcl, which complex. - # uplevel ?level? arg ?arg ...? - # It is a combination between an optional first argument and - # and an args logic. - # - # Most likely, it could be partly solved with a logic for optional - # first arguments (if the number of actual arguments is - # higher than the minimal number of arguments, one could fill optional - # parameter up..... but this calculation requires as well the interactions - # with nonpos arguments, which might be values for positional arguments - # as well.... not, sure, it is worth to invest much time here. + # but seems - at least in this usecase broken. Deactivated + # in source for now. - # TODO: how is upvar affected by the ":"-prefixing? -> AVOID_RESOLVERS ... + # TODO: why is XOTclOUplevelMethodStub/XOTclOUplevelMethod defined + # with "args" while it logically uses the stipulated parameter + # signature (level ...). is this because of the first pos, optional + # parameter? ... same goes for upvar() ... - # this is a tcl question, maybe version dependent. - + # the logic is a tribute to the argument logic in Tcl, which complex. + # uplevel ?level? arg ?arg ...? + # It is a combination between an optional first argument and + # and an args logic. + # + # Most likely, it could be partly solved with a logic for optional + # first arguments (if the number of actual arguments is + # higher than the minimal number of arguments, one could fill optional + # parameter up..... but this calculation requires as well the interactions + # with nonpos arguments, which might be values for positional arguments + # as well.... not, sure, it is worth to invest much time here. + # TODO: how is upvar affected by the ":"-prefixing? -> AVOID_RESOLVERS ... - # TODO: the objectsystems subcommand of ::nsf::configure does - # not really fit in there because it does not allow for configuring - # anything. it is a mere introspection-only command. relocate (can - # we extend standard [info] somehow, i.e., [info objectsystems] + # this is a tcl question, maybe version dependent. + - # what means "configuring anything"? - # maybe you are refering to "configure objectsystems" which is parked there. - # there would be an option to change the internally called methods via - # configure as well, but i think, one is asking for troubles by allowing - # this. - # extending info is possible via the shadowcommands, but the tct - # does not like it. - # - # ad configure: we could fold as well methodproperty and - # objectproperty into configure since these allow as well setting - # and querying.... - # - # configure method METHODHANDLE public - # configure object OBJECT metaclass - # - # but there, the object property is just for quering. - # Another option is define and "info" - # - # ::nsf::info object OBJECT metaclass - # ::nsf::info objectsystems - # - # but if we would fold these into tcl-info, conflicts with - # tcl will arise. - # ISSUE: Object->info->parameter() still needed to retrieve - # objectparameters? + # TODO: the objectsystems subcommand of ::nsf::configure does + # not really fit in there because it does not allow for configuring + # anything. it is a mere introspection-only command. relocate (can + # we extend standard [info] somehow, i.e., [info objectsystems] - # TODO: decide how to deal with @package and @project names (don't - # need namespace delimiters!) + # what means "configuring anything"? + # maybe you are refering to "configure objectsystems" which is parked there. + # there would be an option to change the internally called methods via + # configure as well, but i think, one is asking for troubles by allowing + # this. + # extending info is possible via the shadowcommands, but the tct + # does not like it. + # + # ad configure: we could fold as well methodproperty and + # objectproperty into configure since these allow as well setting + # and querying.... + # + # configure method METHODHANDLE public + # configure object OBJECT metaclass + # + # but there, the object property is just for quering. + # Another option is define and "info" + # + # ::nsf::info object OBJECT metaclass + # ::nsf::info objectsystems + # + # but if we would fold these into tcl-info, conflicts with + # tcl will arise. -} + # ISSUE: Object->info->parameter() still needed to retrieve + # objectparameters? + + # TODO: decide how to deal with @package and @project names (don't + # need namespace delimiters!) + + }