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

Improving support for anonymous classes #2613

Open
wants to merge 37 commits into
base: master
Choose a base branch
from

Conversation

mamazu
Copy link
Contributor

@mamazu mamazu commented Mar 22, 2024

Things that have been done

  • Completion for it works (tests added)
  • Check if there is a better way to generate the name of the anonymous classes

Limitations:

  • The current implementation uses the byteoffset of the class. Meaning that the classname could change if there are textedits that change the text before the class
  • This doesn't go into ClassDeclarationNodes so anoymous classes inside a class wouldn't be recognized?

@mamazu mamazu marked this pull request as draft March 22, 2024 19:54
@mamazu mamazu changed the title First try at implementing it Improving support for anonymous classes Mar 22, 2024
}

if ($child instanceof ObjectCreationExpression) {
// TODO: come up with a good way to generate a class name
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need a better way to generate class names as the code is currently duplicated everywhere.

Copy link
Collaborator

Choose a reason for hiding this comment

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

PHPStan does it like this: https://github.com/dantleech/phpstan-src/blob/f7b89d47cfa1fa636fb571b4315841a9af0e976f/src/Broker/AnonymousClassNameHelper.php#L22-L25

but I don't think this is the correct place to do it.

We can create the reflection class in the resolver?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, technically using the line number is not 100% garanteed to be unique but who has two anon classes on the same line. :D

But what you mean with "creating the reflection class in the resolver"? I wanted to try to avoid making a ReflectionAnonymousClass class as anon classes should be the same except for their weird name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes you are right. A different approach for this would probably make more sense but that would require a lot of refactoring as the fromNode function is used quite a lot.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think it needs refactoring and would also fix the issue Thomas raised below, but would need to show an example.

@mamazu mamazu marked this pull request as ready for review March 24, 2024 23:15
@przepompownia
Copy link
Contributor

From #2612 perspective this seems to be one step ahead but:

image

@mamazu
Copy link
Contributor Author

mamazu commented Mar 25, 2024

What were you trying to do? Generate a class?

@przepompownia
Copy link
Contributor

"Implement contracts" like in #2612

@mamazu
Copy link
Contributor Author

mamazu commented Mar 25, 2024

Now it should work (at least the test for it is green) and it looks like the rest broke.

@przepompownia
Copy link
Contributor

Works for me:

image

continue;
}

if ($child instanceof ObjectCreationExpression && !($child->classTypeDesignator instanceof Node)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this may cause unexpected issues. "reflect classes in" reflects locatable symbols and also it should not need to deeply traverse the AST.

we could consider removing this and instead adding support to $reflector->reflect{Node,AnnonymousClass,Object}($node) for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is this approach won't find all classes anyways. Because we actually have to traverse into class definitions as well. Otherwise we would miss anonymous classes inside other classes. But I don't have an idea how to do improve performance here.

Copy link
Collaborator

@dantleech dantleech Apr 9, 2024

Choose a reason for hiding this comment

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

yes, they need probably to be interpreted inline as types as with the above comment. doing this will mean that "implement contracts" will not automatically work, but at the same time it's only working because of the cache effect in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just saw that reflectClassesIn should probably better be named reflectClassLikeIn 'cause it also returns interfaces enums etc. which are completely irrelevant for the "Implement contracts". But that's not a problem of this PR.

However I get what you're saying, I'm not sure if its based on cache in this situation because the source code builder reflects the same structure again and should also build the same list of ClassLike nodes. On the other hand I'm quite familiar with the concept of inline types and how I would go about and implement this. Do we already have an example for this?

@przepompownia
Copy link
Contributor

przepompownia commented Apr 19, 2024

At the moment I have no occasion to work with anonymous classes, but have merged the recent version of this PR into my experimental branch and can report possible side effects.

@dantleech
Copy link
Collaborator

just to be clear, it's unlikely to be merged with it's current implementation. but hopefully I can find some time to look more into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants