This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 251652 - @return object provokes wrong code completion
Summary: @return object provokes wrong code completion
Status: NEW
Alias: None
Product: php
Classification: Unclassified
Component: Editor (show other bugs)
Version: 8.0.2
Hardware: All All
: P4 normal (vote)
Assignee: Tomas Mysik
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-04-04 22:34 UTC by Gregory_Lundberg
Modified: 2016-06-08 15:52 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gregory_Lundberg 2015-04-04 22:34:27 UTC
Consider

        class Subj{
            function SubjFunc() { }
        }

        class Test {
            /**
             * @return object
             */
            function TestFunc() { return (object) new Subj(); }
        }
        
        $t = new Test();
        $o = $t->TestFunc(); // Probably should want a vardoc here.
        $o-> // Wrong auto-completion here. Should get nothing at all.

The @return object should mean Test::TestFunc() is returning a generic object, for which there should be to auto-completion as it has no members of any kind. Instead, we're offered auto-completion for the containing class (Test); which has nothing, whatsoever, to do with what the function Test::TestFunc returns.

If we know (as here) that the generic object is actually a specific instance (Subj in this example), a vardoc (/* @var $o Subj */) should give the correct auto-completion. As is, it merges Subj and Test so, if we hunt, we can find what we need. But if we're not careful we could select TestFunc (not defined on $o) instead of SubjFunc (which is defined on $o).

In other words instead of meaning "some sort of object", it's being taken to mean "an object of the type which defined me" (which will only rarely be the correct guess).
Comment 1 Gregory_Lundberg 2015-04-04 23:04:46 UTC
NB. The cast to (object) for the new Subj() is not needed to exhibit the error. The @return is sufficient. If you do the cast and omit the @return it behaves correctly.
Comment 2 Tomas Mysik 2016-06-07 15:06:26 UTC
It seems to me a bit strange that you are returning some class that in fact does not exist at all. If you want to return some base object (like java.lang.Object in Java), you should perhaps use "stdClass".

Thanks for reporting.
Comment 3 Gregory_Lundberg 2016-06-07 22:24:36 UTC
No, I just boiled it down to the minimum required to exhibit the error.

Turned out, as the followup stated, the cast to (object) is incorrect.

Note the actual object instance being returned is 'Subj'

Note also the DOCUMENTED return type is '@return object' .. in other words I'm admitting I return an object, but don't want to commit to it being a specific type of object.

So, when I DOCUMENT that it's a generic, not methods or members, object, the auto-completion ignored me and offers the methods and members from 'Test' (not 'Subj' and not a generic object).
Comment 4 Gregory_Lundberg 2016-06-07 22:40:08 UTC
Note, also, that one would expect a vardoc to solve the issue.

Instead, the vardoc MERGED the methods from Subj with the methods from Test as suggestions.

In my case, I didn't want to ADMIT to it being a specific type (here, 'Subj') and, with no vardoc, it 'merged' the empty list (the correct list of methods from a generic object) with the methods from 'Test'.

So, the problem is 'Test' has no relationship, whatsoever, with the return type. Yet auto-completion is including it AS IF it where a super-type of 'Subj' .. which, of course, it is NOT.
Comment 5 Tomas Mysik 2016-06-08 05:38:08 UTC
(In reply to Gregory_Lundberg from comment #3)
> Note also the DOCUMENTED return type is '@return object' .. in other words
> I'm admitting I return an object, but don't want to commit to it being a
> specific type of object.
> 
> So, when I DOCUMENT that it's a generic, not methods or members, object, the
> auto-completion ignored me and offers the methods and members from 'Test'
> (not 'Subj' and not a generic object).

If the return type is not found by NetBeans (like in this case), NetBeans tries to resolve the return type from the declaration.
Comment 6 Tomas Mysik 2016-06-08 05:40:50 UTC
(In reply to Gregory_Lundberg from comment #4)
> Note, also, that one would expect a vardoc to solve the issue.
> 
> Instead, the vardoc MERGED the methods from Subj with the methods from Test
> as suggestions.
> 
> In my case, I didn't want to ADMIT to it being a specific type (here,
> 'Subj') and, with no vardoc, it 'merged' the empty list (the correct list of
> methods from a generic object) with the methods from 'Test'.
> 
> So, the problem is 'Test' has no relationship, whatsoever, with the return
> type. Yet auto-completion is including it AS IF it where a super-type of
> 'Subj' .. which, of course, it is NOT.

As I wrote, simply return the basic PHP stdClass [1] or define "dummy" empty class, in your case:

class object {}

Thanks for reporting.
[1] http://php.net/manual/en/reserved.classes.php
Comment 7 Gregory_Lundberg 2016-06-08 12:21:54 UTC
One of us seems to be missing the point.

The object returned *IS* of a type. In my code example, 'Subj'. In my example it has a member function 'SubjFunc'.

The DOCUMENTED return type is the generic 'object'.

The example SHOULD read:
 function TestFunc() { return new Subj(): }

The auto-completion DOES NOT offer ONLY members of 'Subj'

It appears when NetBeans is GUESSING the member functions of 'Subj' it is incorrectly GUESSING the Subj, clearly NOT related to Test, somehow includes all member functions of Test and offers those.

This leads to all sorts of human-error problems and promotes bugs.

Casting the result ('Subj') to some other type ('stdObject') may solve the problem. But you're requiring the library designer to (1) know that there will be down-stream bugs and (2) code around the bugs with a slimy hack rather than fixing the issue.
Comment 8 Gregory_Lundberg 2016-06-08 14:59:50 UTC
I think the problem is you're reading PHP.net and thinking it has to do with the issue.

The issue is NOT the PHP code.

The issue is the COMMENTS which Netbeans *is* intepreting, which DOCUMENT the type as the generic 'object'

As I said, the example is the *minimum* .. and that INCLUDES the '@return object' comment.

If you want to ADD to the confusion NetBeans exhibits, then add a (not shown) vardoc comment, as explained.
Comment 9 Gregory_Lundberg 2016-06-08 15:22:55 UTC
This works correctly, but has a PHP language case I don't want:

class Subj { function SubjFunc() {} }

class Test { function TestFunc() { return (object) new Subj{}: } }

$t = new Test();
$o = $t->TestFunc();
$o-> // Autocompletion offers members of Subj only

----------------

This fails, but DOCUMENTS what I want without unneeded PHP syntax:

class Subj { function SubjFunc() {} }

class Test {
/**
 * @return object
 */
 function TestFunc() { return new Subj(); }
}

$t = new Test();
$o = $t->TestFunc();
$o-> // Autocompletion offers members of Test and not Subj .. totally wrong

------------------

This seems to increase the confusion:

class Subj { function SubjFunc() {} }

class Test {
/**
 * @return object
 */
 function TestFunc () { return new Subj(); }
}
$t = new Test();
/* @var $o Subj */ $o = $t->TestFunc();
$o-> // Autocompletion offers members of Subj (good) PLUS Test (Huh? Wrong!)

----

PHP.net does specify @return and @var comments and has nothing to do with the issue.
Comment 10 Gregory_Lundberg 2016-06-08 15:31:05 UTC
It's been a year since reported. I'm not working on that project any longer. I simply added a comment to the documentation to NOT RELY upon NetBeans and carefully examine your code if you do use NetBeans. I'm working off memory for much of this, now.

My issue is I want to return an object (any object, don't care the type, don't care if the user can see inside it or if NetBeans is offering members from it for autocompletion). BUT in my DOCUMENTATION I want to simply DOCUMENT it as returning 'an object'.  If the user, then, later, peeks inside and uses 'SubjFunc' and, at a later date I change to another object .. well, to bad!, you were told it was 'an object' and you presumed it was a specific type I did NOT commit to. RTFM, dear user!
Comment 11 Gregory_Lundberg 2016-06-08 15:52:06 UTC
Let's have some fun and use two classes, both with a function with returns an instance of a third class.

Here is the common third class:
  class Subj { function Correct() {} }

And here are the generators:

  class First {
  /**
   * @return object
   */
  function FirstWrong() { return new Subj{}; }
  }

  class Second {
  /**
   * @return object
   */
  function SecondWrong() { return new Subj(); }
  }

Now, let's do some setup:

$f = new First();
$s = new Second();

/* @var $a Subj */ $a = $f->FirstWrong();

/* @var $b Subj */ $b = $s->SecondWrong();

$c = new Subj();

Now, start a new statement and check the autocompletion.

$a-> // Offers First::FirstWrong (does not exist) and Subj::Correct (does exist)

$b-> // Offers Second::SecondWrong (does not exist) and Subj::Correct (does exist)

$c-> // Offset only Subj::Correct, as one would expect for $a and $b, too.

And, of course, when I generate the documentation, both FirstWrong and SecondWrong are DOCUMENTED are returning 'an object' without mentioning Subj so, when the user ignores that and I change Subj at a later date and Subj::Correct no longer exists .. well, that's just too bad, the user needs to fix their code.