Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new phan rule PhanMismatchReturn #4914

Merged
merged 25 commits into from
Sep 18, 2019
Merged

Add new phan rule PhanMismatchReturn #4914

merged 25 commits into from
Sep 18, 2019

Conversation

johnsaigle
Copy link
Contributor

@johnsaigle johnsaigle commented Jun 27, 2019

Brief summary of changes

This PR adds the new phan rule PhanMismatchReturn which flags code that is declared to return a type but in reality returns a different type. e.g.

/**
* @return int
*/
function returnInt() {
    return 'hello';
}

Turns out we do this all over the place in LORIS so this PR is pretty big.

A lot of phan errors came up related to #4308 so this PR also fixes a lot of those.

There are also minor optimizations/rewrites of functions that were needlessly complicated. In pretty much every case the replacements should be logically equivalent and hopefully more maintainable.

@johnsaigle johnsaigle added Cleanup PR or issue introducing/requiring at least one clean-up operation Testing PR contains test plan or automated test code (or config files for Travis) Meta PR does something that organizes, upgrades, or manages the functionality of the codebase State: Discussion required PR or issue that requires the resolution of a discussion with the relevant parties to proceed labels Jun 27, 2019
@@ -372,7 +372,7 @@ function display()
$this->tpl_data['complete'] = true;

$this->updateStatus('Complete');
$Responses = $DB->update(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused. same with below.

@@ -152,8 +152,6 @@ class Candidate_List extends \NDB_Menu_Filter
'participantstatus' => $participant_status_options,
'useedc' => $config->getSetting("useEDC"),
];

return true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you see this line deleted in this PR in other files, it typically means that the function should actually return void.

@@ -208,7 +208,9 @@ class Create_Timepoint extends \NDB_Form
WHERE CenterID =:cid",
array('cid' => $siteID)
);
$psc_labelOptions[$siteID] = $center['Name'];
if (!is_null($center)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another theme in this PR is verifying that DB results are not null. Since the pselect* family does not have any return types it is possible for them to return null instead of the expected array of data. This causes phan to get upset when we try to access an array key without first ensuring that the DB result is not null.

@@ -43,7 +43,7 @@
} else {
$target_path = $base_path . $fileName;
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_path)) {
$success = $DB->insert(
Copy link
Contributor Author

@johnsaigle johnsaigle Jun 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

insert + update always return void so they should not be assigned to a value.

@driusan
Copy link
Collaborator

driusan commented Jul 2, 2019

This should go to major, not the 21.0-release branch at this point.

@johnsaigle
Copy link
Contributor Author

Has 21 been merged back into major? I'll mark this as Needs Rebase for now but I think changing the base branch right now will make all the changes meaningless.

@johnsaigle johnsaigle added State: Needs rebase PR that needs to be rebased to proceed (conflicts, wrong branch...) State: Needs work PR awaiting additional work by the author to proceed labels Jul 2, 2019
@johnsaigle johnsaigle added this to the 22.0.0 milestone Jul 3, 2019
@johnsaigle
Copy link
Contributor Author

johnsaigle commented Jul 10, 2019

src/Middleware/MiddlewareChainerMixin.php:46 PhanTypeMismatchDeclaredReturn Doc-block of withMiddleware contains declared return type \LORIS\Middleware\MiddlewareChainerMixin which is incompatible with the return type \LORIS\Middleware\MiddlewareChainer declared in the signature
src/Middleware/MiddlewareChainerMixin.php:62 PhanTypeMismatchReturn Returning type \LORIS\Middleware\MiddlewareChainerMixin but withMiddleware() is declared to return \LORIS\Middleware\MiddlewareChainer
test/unittests/NDB_BVL_FeedbackTest.php:73 PhanTypeMismatchReturn Returning type \PHPUnit_Extensions_Database_DataSet_CompositeDataSet but getDataSet() is declared to return \PHPUnit\DbUnit\DataSet\IDataSet

These are the remaining phan errors after this rule is applied. I'm not exactly sure how to solve these ones so any help would be appreciated. Doing a straightforward change on the return types listed above just creates another kind of conflict.

Pinging @driusan because I think I'll need your help here

@@ -47,79 +47,79 @@ abstract class AbstractServerProcess
/**
* ID of the process when recorded in the database.
*
* @var int.
* @var int
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newer versions of phan don't like the . after the type

@johnsaigle johnsaigle added State: Blocked PR or issue awaiting an external event such as the merge or another PR to proceed and removed State: Needs rebase PR that needs to be rebased to proceed (conflicts, wrong branch...) State: Discussion required PR or issue that requires the resolution of a discussion with the relevant parties to proceed State: Needs work PR awaiting additional work by the author to proceed labels Jul 10, 2019
@johnsaigle
Copy link
Contributor Author

The only remaining phan issue (i.e. what is causing Travis to fail) is caused by a reference to DbUnit which is removed by #4433.

Until it's merged, this PR will be marked as Blocked.

@johnsaigle johnsaigle changed the base branch from 21.0-release to major July 17, 2019 15:51
@johnsaigle johnsaigle added [branch] major and removed State: Blocked PR or issue awaiting an external event such as the merge or another PR to proceed [branch] major labels Jul 24, 2019
@johnsaigle johnsaigle changed the base branch from major to minor July 24, 2019 21:38
@johnsaigle johnsaigle added the State: Needs work PR awaiting additional work by the author to proceed label Jul 29, 2019
@johnsaigle
Copy link
Contributor Author

johnsaigle commented Jul 30, 2019

php/libraries/NDB_Factory.class.inc:112 PhanUndeclaredFunction Call to undeclared function \MockNDB_Config()
php/libraries/NDB_Factory.class.inc:147 PhanUndeclaredFunction Call to undeclared function \MockUser()

EDIT:

php/libraries/NDB_Factory.class.inc:122 PhanTypeMismatchReturn Returning type \MockNDB_Config but config() is declared to return \NDB_Config

@driusan These are my remaining phan errors. Phan doesn't seem to understand what we're doing were with PHPUnit.

I tried using the PHPUnit extensions for phan -- no change.

I also tried using Mock::generate(CLASS) but that doesn't work with our tests.

Any thoughts?

@driusan
Copy link
Collaborator

driusan commented Jul 30, 2019

Are you sure those line numbers are right? In NDB_Factory for those lines I see:

line 112: return self::$config
line 147: */

The "MockUser" and "MockNDB_Config" references near those lines both have the new keyword before them, so I would expect phan to be smart enough to at least realize they aren't function calls.

@johnsaigle
Copy link
Contributor Author

johnsaigle commented Jul 30, 2019

Yes, sorry I reverted wrong. My issue is this:

php/libraries/NDB_Factory.class.inc:122 PhanTypeMismatchReturn Returning type \MockNDB_Config but config() is declared to return \NDB_Config

If I add \MockNDB_Config to the @return it gives an error about this class not existing, e.g.

php/libraries/NDB_Factory.class.inc:107 PhanTypeMismatchDeclaredReturn Doc-block of config contains declared return type \MockNDB_Config which is incompatible with the return type \NDB_Config declared in the signature

php/libraries/NDB_Factory.class.inc:109 PhanUndeclaredTypeReturnType Return type of config() is undeclared type \MockNDB_Config

@driusan
Copy link
Collaborator

driusan commented Jul 30, 2019

I don't think we'll ever be able to fix that since from what I can tell PHPUnit creates the mock classes using eval. https://github.com/sebastianbergmann/phpunit/blob/master/src/Framework/MockObject/MockClass.php#L42 .. the mock objects are dynamically generated code, they're not very amenable to static analysis.

Since PHP type hinting doesn't support sum types while doc comments do, our options are either:

  1. Tell phan to ignore those 2 lines and add a comment explaining why, since we know that it's an instance of NDB_Config even if phan doesn't.
  2. Remove the type hinting from the signature but leave it in the docblock, so that phan can still analyze the types but doesn't flag the mismatch as an error.

Short of refactoring the code, I think this is one of the rare cases where I'd prefer 1, but I have nothing against 2 either.

@johnsaigle
Copy link
Contributor Author

I'd prefer approach 1) too. I'll add the suppression and a note explaining it

@johnsaigle
Copy link
Contributor Author

johnsaigle commented Aug 5, 2019

I'm getting similar issues with:

php/libraries/NDB_Factory.class.inc:112 PhanTypeMismatchReturn Returning type null but config() is declared to return \NDB_Config
3926php/libraries/NDB_Factory.class.inc:157 PhanTypeMismatchReturn Returning type null but user() is declared to return \User

I'm going to also add suppressions for these because they're the same species of issue.

@johnsaigle johnsaigle removed the State: Needs work PR awaiting additional work by the author to proceed label Aug 19, 2019
@johnsaigle johnsaigle requested a review from driusan August 19, 2019 22:07
" where id=$parent_id";
$value = $DB->pselectRow($query, array());
$value = $DB->pselectRow($query, array());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use label instead of direct value in query.

modules/help_editor/php/helpfile.class.inc Outdated Show resolved Hide resolved
@@ -99,7 +99,7 @@ public function handle(ServerRequestInterface $request) : ResponseInterface
*
* @param ServerRequestInterface $request The incoming PSR7 request
*
* @return array
* @return array|\Psr\Http\Message\ResponseInterface
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense to me. Why would a toArray function return a PSR ResponseInterface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phan wants this because of the Exception case that returns a 400 response.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.. it's still a code smell, but it's fine for this PR since it's just documenting what's already there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Cleanup PR or issue introducing/requiring at least one clean-up operation Meta PR does something that organizes, upgrades, or manages the functionality of the codebase Testing PR contains test plan or automated test code (or config files for Travis)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants