changeset 29032:2cbfd91aafb9 stable

improve behavior of exist for finding class constructors (bug #59304) * variables.cc (symbol_exist): Also find class constructors when name is something like "@ftp/ftp", "@ftp/ftp.m", "ftp.m", or "ftp". New tests.
author John W. Eaton <jwe@octave.org>
date Thu, 05 Nov 2020 16:51:25 -0500
parents a0ff81c8b8e8
children c27ce309c079 e3bc897115ed
files libinterp/corefcn/variables.cc
diffstat 1 files changed, 68 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/variables.cc	Thu Nov 05 21:41:44 2020 +0100
+++ b/libinterp/corefcn/variables.cc	Thu Nov 05 16:51:25 2020 -0500
@@ -233,26 +233,70 @@
   // We shouldn't need to look in the global symbol table, since any name
   // that is visible in the current scope will be in the local symbol table.
 
-  // Command line function which Matlab does not support
-  if (search_any)
-    {
-      octave_value val = symtab.find_cmdline_function (name);
-
-      if (val.is_defined ())
-        return 103;
-    }
-
   if (search_any || search_file || search_dir)
     {
-      octave::tree_evaluator& tw = interp.get_evaluator ();
+      bool have_fcn_ext = false;
+
+      std::string xname = name;
+      std::string ext;
+
+      size_t pos = name.rfind ('.');
+
+      if (pos != std::string::npos)
+        {
+          ext = name.substr (pos+1);
 
-      std::string file_name = tw.lookup_autoload (name);
+          if (ext == "m" || ext == "oct" || ext == "mex")
+            {
+              xname = name.substr (0, pos);
+              have_fcn_ext = true;
+            }
+        }
 
-      if (file_name.empty ())
+      std::string file_name;
+
+      if (search_any || search_file)
         {
           octave::load_path& lp = interp.get_load_path ();
 
-          file_name = lp.find_fcn (name);
+          // Class constructor.
+          file_name = lp.find_method (xname, xname);
+
+          if (have_fcn_ext && ! file_name.empty ())
+            {
+              pos = file_name.rfind ('.');
+
+              if (pos != std::string::npos)
+                {
+                  std::string fext = file_name.substr (pos+1);
+
+                  if (ext != fext)
+                    file_name = "";
+                }
+            }
+
+          if (search_any && file_name.empty ())
+            {
+              // Command line function which Matlab does not support
+              octave_value val = symtab.find_cmdline_function (xname);
+
+              if (val.is_defined ())
+                return 103;
+            }
+
+          // Autoloads can only have simple names without extensions.
+
+          if (! have_fcn_ext && file_name.empty ())
+            {
+              octave::tree_evaluator& tw = interp.get_evaluator ();
+
+              file_name = tw.lookup_autoload (name);
+            }
+
+          // Use original name here.
+
+          if (file_name.empty ())
+            file_name = lp.find_fcn (name);
         }
 
       size_t len = file_name.length ();
@@ -303,14 +347,9 @@
         return 0;
     }
 
-  if (search_any || search_builtin)
-    {
-      if (symtab.is_built_in_function_name (name))
-        return 5;
-
-      if (search_builtin)
-        return 0;
-    }
+  if ((search_any || search_builtin)
+      && symtab.is_built_in_function_name (name))
+    return 5;
 
   return 0;
 }
@@ -497,6 +536,14 @@
 %!assert (exist ("fftw", "file"), 3);
 %!assert (exist ("fftw", "builtin"), 0);
 
+%!assert (exist ("ftp"), 2);
+%!assert (exist ("ftp.m"), 2);
+%!assert (exist ("@ftp/ftp"), 2);
+%!assert (exist ("@ftp/ftp.m"), 2);
+
+%!assert (exist ("inputParser"), 2);
+%!assert (exist ("inputParser.m"), 2);
+
 %!assert (exist ("sin"), 5)
 %!assert (exist ("sin", "builtin"), 5)
 %!assert (exist ("sin", "file"), 0)