changeset 28514:fab862fedf85 stable

allow help to find docstrings for classdef classes and methods (bug #43047) * help.cc (help_system::raw_help_from_symbol_table): Also find docstrings from classdef meta objects (both classes and methods). * cdef-class.h, cdef-class.cc (cdef_class::cdef_class_rep, cdef_class): Store docstring for class and provide access. * ov-classdef.h, ov-classdef.cc (octave_classdef_meta::doc_string): New function to provide access to doc strings for classdef objects and methods. * ov-fcn.h (octave_function::doc_string): Now virtual. New argument for method name.
author John W. Eaton <jwe@octave.org>
date Fri, 29 May 2020 10:57:04 -0400
parents 59c6625e0180
children 49f4d7814760
files libinterp/corefcn/help.cc libinterp/octave-value/cdef-class.cc libinterp/octave-value/cdef-class.h libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-classdef.h libinterp/octave-value/ov-fcn.h
diffstat 6 files changed, 62 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/help.cc	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/corefcn/help.cc	Fri May 29 10:57:04 2020 -0400
@@ -523,33 +523,47 @@
                                                 std::string& h, std::string& w,
                                                 bool& symbol_found) const
   {
-    bool retval = false;
+    std::string meth_nm;
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
     octave_value val = symtab.find_function (nm);
 
+    if (! val.is_defined ())
+      {
+        size_t pos = nm.rfind ('.');
+
+        if (pos != std::string::npos)
+          {
+            meth_nm = nm.substr (pos+1);
+
+            val = symtab.find_function (nm.substr (0, pos));
+          }
+      }
+
     if (val.is_defined ())
       {
         octave_function *fcn = val.function_value ();
 
         if (fcn)
           {
+            // FCN may actually be a classdef_meta object.
+
             symbol_found = true;
 
-            h = fcn->doc_string ();
-
-            retval = true;
+            h = fcn->doc_string (meth_nm);
 
             w = fcn->fcn_file_name ();
 
             if (w.empty ())
               w = fcn->is_user_function () ? "command-line function"
-                                           : "built-in function";
+                : "built-in function";
+
+            return true;
           }
       }
 
-    return retval;
+    return false;
   }
 
   bool help_system::raw_help_from_file (const std::string& nm,
--- a/libinterp/octave-value/cdef-class.cc	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/octave-value/cdef-class.cc	Fri May 29 10:57:04 2020 -0400
@@ -897,6 +897,8 @@
 
     retval = cdm.make_class (full_class_name, slist);
 
+    retval.doc_string (t->doc_string ());
+
     // Package owning this class
 
     if (! t->package_name ().empty ())
--- a/libinterp/octave-value/cdef-class.h	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/octave-value/cdef-class.h	Fri May 29 10:57:04 2020 -0400
@@ -151,6 +151,10 @@
 
       bool is_meta_class (void) const { return meta; }
 
+      void doc_string (const std::string& txt) { m_doc_string = txt; }
+
+      std::string doc_string (void) const { return m_doc_string; }
+
     private:
 
       void load_all_methods (void);
@@ -174,6 +178,8 @@
 
       std::string directory;
 
+      std::string m_doc_string;
+
       // The methods defined by this class.
 
       std::map<std::string,cdef_method> method_map;
@@ -374,6 +380,10 @@
 
     bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
 
+    void doc_string (const std::string& txt) { get_rep ()->doc_string (txt); }
+
+    std::string doc_string (void) const { return get_rep ()->doc_string (); }
+
   public:
 
     enum
--- a/libinterp/octave-value/ov-classdef.cc	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/octave-value/ov-classdef.cc	Fri May 29 10:57:04 2020 -0400
@@ -428,6 +428,29 @@
   return retval;
 }
 
+std::string octave_classdef_meta::doc_string (const std::string& meth_name) const
+{
+  if (object.is_class ())
+    {
+      octave::cdef_class cls (object);
+
+      if (meth_name.empty ())
+        return cls.doc_string ();
+
+      octave_value ov_meth = cls.get_method (meth_name);
+
+      if (ov_meth.is_defined ())
+        {
+          octave_function *fcn = ov_meth.function_value ();
+
+          if (fcn)
+            return fcn->doc_string ();
+        }
+    }
+
+  return "";
+}
+
 octave_value_list
 octave_classdef_superclass_ref::execute (octave::tree_evaluator& tw,
                                          int nargout,
--- a/libinterp/octave-value/ov-classdef.h	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/octave-value/ov-classdef.h	Fri May 29 10:57:04 2020 -0400
@@ -222,6 +222,8 @@
 
   bool is_classdef_constructor (const std::string& cname = "") const;
 
+  std::string doc_string (const std::string& meth_name) const;
+
 private:
 
   octave::cdef_meta_object object;
--- a/libinterp/octave-value/ov-fcn.h	Fri May 29 10:56:22 2020 -0400
+++ b/libinterp/octave-value/ov-fcn.h	Fri May 29 10:57:04 2020 -0400
@@ -223,7 +223,11 @@
 
   void document (const std::string& ds) { doc = ds; }
 
-  std::string doc_string (void) const { return doc; }
+  virtual std::string
+  doc_string (const std::string& /*meth_name*/ = "") const
+  {
+    return doc;
+  }
 
   virtual void unload (void) { }