pbyrne84 / DynamicReturnTypePlugin

135 stars 7 forks source link

(Feature Request) Chained method evaluation #71

Open chasepeeler opened 6 years ago

chasepeeler commented 6 years ago

Not sure how feasible this is, but I figured I'd put it in.

The plugin handles this situation just fine: $entityManager->find("DB:MyModel",$id); I have a replacement function for position 0 of the find method, which replaces "DB" with the namespace that it is an alias for. So, the return type gets treated as \My\Namespace\Models\MyModel

What it doesn't handle is something like this: $entityManager->getRepository("DB:MyModel")->findBy(["name"=>$name]); In this instance, I need the findBy method of the repository class to return a type based on the value passed into getRepository, e.g. \My\Namespace\Models\MyModel[]

I think it would basically require the ability to have the getRepository method return a pseudo-type, and then being able to define a rule on the find method using that pseudo-class. Here's a possible solution, which requires a new, third parameter passed into the replacement functions representing the source class, and the ability to specify wildcards in the "class" directive.

//config file
{
  "methodCalls": [
     {
      "class": "EntityManager",
      "method": "getRepository",
      "position":0,
      "fileReturnTypeReplacementCall": [
          "ReturnTypes.js",
          "createPseudoRepository"
       ]
     },
     {
      "class": "pseudoRepository_%",
      "method": "findBy",
      "position": 0,
      "fileReturnTypeReplacementCall": [
          "ReturnTypes.js",
          "getFindByReturn"
       ]
     },
   ]
}
//ReturnTypes.js

function createPseudoRepository(ns,c){
   return "pseudoRepository_"+c.replace("DB:","");
}

function getFindByReturn(ns,c,sourceClass){
  sourceClass = sourceClass.replace("pseudoRepository_","");
  return "\\My\\Namespace\\Models\\"+sourceClass+"[]";
}

I don't think you do anything that requires the functions return actual types, so, the pseudoclass idea shouldn't require anything special. That would mean the only real updates are accepting wildcards in the "class" attribute, which could be useful outside of this, and then passing that as a third parameter into the functions.

chasepeeler commented 6 years ago

Also, I know you aren't doing much on this right now due to the PhpTypeProvider change. I'd still be curious your thoughts on the feasibility of this though, assuming you are able to resume working on it at some point.

ezzatron commented 6 years ago

I would also appreciate this feature. My mocking library, Phony, uses this kind of arrangement to create mocks:

$handle = mock(ClassA::class);
$mock = $handle->get(); // $mock is an instance of ClassA

I've recently had a user requesting better support for PhpStorm (eloquent/phony#229), and there's not much I can do at the moment aside from writing a custom PhpStorm plugin, or changing my API.

Also happy to help out by submitting PRs if you have an idea of how this could be accomplished.