--level used: 6Using master I encountered the following bug ( similar but not quite as https://github.com/nunomaduro/larastan/issues/516 ):
------ --------------------------------------------------------------------------------------------------------
Line Some/Klass.php
------ --------------------------------------------------------------------------------------------------------
Class self was not found while trying to analyse it - autoloading is probably not configured properly.
56 Class self was not found while trying to analyse it - autoloading is probably not configured properly.
56 Class self was not found while trying to analyse it - autoloading is probably not configured properly.
56 Class self was not found while trying to analyse it - autoloading is probably not configured properly.
------ --------------------------------------------------------------------------------------------------------
Not kidding, the first line does truly not report a (line) number. Since it doesn't "crash", adding --debug didn't reveal anything.
The reported line looks like this:
Model
::whereIn(
'some_column',
$anotherModel
->children() # <- a `HasMany` relation defined as `return $this->hasMany(self::class, 'parent_id');`
->pluck('id')
);
In my case its triggered because I call pluck directly on the relation; if I insert ->get() the reported error is gone:
Model
::whereIn(
'some_column',
$anotherModel
->children()
->get() # <- line added
->pluck('id')
);
I think the repeated reported in due to the span across so many lines, it changes when I join the lines etc.
_Originally posted by @mfn in https://github.com/nunomaduro/larastan/issues/516#issuecomment-613123559_
Btw I _think_ this is the error which seems to prevent me a baseline, never seen this 馃槃 but I assume so because of the missing line number:
> phpstan analyse --configuration=phpstan.neon app --generate-baseline
978/978 [鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔] 100%
[WARNING] Baseline generated with 115 errors.
Some errors could not be put into baseline. Re-run PHPStan and fix
them.
:-)
Ah, can't be manually ignored either:
Error message "Class self was not found while trying to analyse it - autoloading is probably not configured properly." cannot be ignored, use excludes_analyse instead.
Excluding these classes isn't an option, so I hit a dead end integrating larastan 馃槺
Oh, it's getting weird I see :smile: I'll try to fix it today.
The issue is self::class is not resolved to an actual class name. Normally PHPStan can do that, but in this case, I'm doing some weird stuff and try to parse file by myself with PHP-Parser. So I also need to resolve names. I tried using NameResolver visitor but didn't seem to do the job.
So looks like it'll take little more time than I thought since I need to learn some more stuff about PHP-Parser :smile:
..or ask @ondrejmirtes
$scope->resolveName() will do.
I'm doing some weird stuff and try to parse file by myself with PHP-Parser.
Can you point me to the specific code you're working with? Maybe I'll be able to suggest some improvements.
Basically, I want to change the return type of a class method. But the return type depends on something in the body of the method.
For example for this method:
public function accounts(): HasMany
{
return $this->hasMany(Account::class);
}
I want to convert the return type to HasMany<Account>
In the ideal world, users would define this return type on their own. But I want to make it easier for them. If we force them to annotate all of their relations, that would be a big effort I guess.
So for that case, I wrote a DynamicMethodReturnTypeExtension. And in there, I'm parsing the file that the method defined in, finding the correct method call node, accounts for example, then finding the return statement, then finding the first argument of the method call. Account::class for example from the code above.
So I realized I need a new scope for only this file. So I did something like this
$scope = $this->scopeFactory->create(\PHPStan\Analyser\ScopeContext::create($fileName));
$classScope = $scope->enterClass($classReflection);
Then I can do something like this:
$argValue = $methodCall->args[0]->value;
$argType = $classScope->getType($argValue);
to get the arg type. This will work 99% of all the cases. Cause that first argument is almost always a string, like Account::class, 'App\Account' or self:class
So overall is this a good idea? Or should we just say users to put the generic annotations to their relation methods?
This is fine. I'm doing something similar in phpstan-doctrine: https://github.com/phpstan/phpstan-doctrine/blob/b67c0cc3e6411d0dceda81ebd34c56d6120dec48/src/Type/Doctrine/QueryBuilder/QueryBuilderMethodDynamicReturnTypeExtension.php#L159-L198
For example, if someone is calling $this->createBaseQuery()->select('e'), in case createBaseQuery returns QueryBuilder I'm gonna inspect the createBaseQuery method body source code to find how the QueryBuilder is defined.
Can you point me to:
self needs to appear somewhere in it.In the current state, the extension does not have the latest changes. I started locally yesterday. And got it working today. With the changes to use a new scope for the file. But here is the current state. And this was failing when analyzing for example
public function children(): HasMany
{
return $this->hasMany(self::class, 'parent_id');
}
It was returning HasMany<self>
But with the new changes, it works correctly. I'll clean up the code and open a PR. So then maybe you can take a look and give some suggestions.
Yeah, ping me once you do. When I look at the current state, this logic is totally unnecessary:
$argValue = $methodCall->args[0]->value;
if ($argValue instanceof Node\Expr\ClassConstFetch && $argValue->class instanceof Node\Name) {
return $argValue->class->toString();
}
if ($argValue instanceof Node\Scalar\String_) {
return $argValue->value;
}
You can replace it with:
$argType = $scope->getType($methodCall->args[0]->value);
if ($argType instanceof ConstantStringType) {
return $argType->getValue();
}
And it will also account for code like:
$class = self::class;
return $this->hasMany($class, 'parent_id');
which the pure AST approach doesn't.
@mfn This should be fixed with #533 Can you test again after pulling the latest master?
It works, thank you! 鉂わ笍