- Notifications
You must be signed in to change notification settings - Fork8.1k
FixTypeName.GetReflectionType() to work when theTypeName instance represents a generic type definition within aGenericTypeName#24985
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
… generic type can be found in cache
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.
Files not reviewed (1)
- test/powershell/Language/Parser/Parsing.Tests.ps1: Language not supported
Comments suppressed due to low confidence (1)
src/System.Management.Automation/engine/parser/SymbolResolver.cs:717
- Ensure that the new behavior of setting the cached type for 'genericTypeName.TypeName' when 'GetReflectionType()' returns null is covered by tests.
((ISupportsTypeCaching)genericDefinition).CachedType = foundType.GetGenericTypeDefinition();/azp run |
| Azure Pipelines successfully started running 2 pipeline(s). |
@MartinGC94 Can you please also review this PR? Thank you! |
Uh oh!
There was an error while loading.Please reload this page.
It fixes my real world scenario and the fix itself seems reasonable. Thanks for the quick fix :) |
GenericTypeName.TypeName as needed when the generic type is found in cacheTypeName.GetReflectionType() to work when theTypeName instance represents a generic type definition within aGenericTypeName| if(genericArgumentCount>0&&!_name.Contains('`')) | ||
| { | ||
| _genericArgumentCount=genericArgumentCount; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Usually, we expect a constructor to throw an exception if the argument is unexpected. But here we perform a correction of the argument. It's amazing. I'm afraid this may provoke accidental misuse of this constructor in the future. At the very least, it would be good to add a comment with examples of the scenarios we address and explaining why this correction is needed in this place.
Alternatively, we could perform a check at the call location and pass the correct arguments.
It could be even better to use a template likeprivate static TypeName TypeName.CreateAlternativeGenericTypeName() with a comprehensive description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This "try alternate name" thing happens in multiple places, which is common when dealing with generic type resolution. Comments were added in theGetReflectionType() to explain why we only fall back to alternate name even ifgenericArgumentCount is set.
As for the scenario for using this constructor, the XML comment calls it out and it's also easy to understand by looking at where it's used. So, I don't think more comments are needed.
I can add a check to throw whengenericArgumentCount is a negative value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
LGTM!
ef64132 intoPowerShell:masterUh oh!
There was an error while loading.Please reload this page.
microsoft-github-policy-servicebot commentedMar 17, 2025 • edited by unfurl-linksbot
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by unfurl-linksbot
Uh oh!
There was an error while loading.Please reload this page.
📣 Hey@daxian-dbw, how did we do? We would love to hear your feedback with the link below! 🗣️ 🔗https://aka.ms/PSRepoFeedback |
Uh oh!
There was an error while loading.Please reload this page.
PR Summary
Fix#24982
When a generic type expression is parsed for the second time, the generic type can be found in cache, and hence the symbol resolver won't go through the code path to resolve
genericTypeName.TypeName, which represents the generic type definition. Therefore, unlike the first-time parsing, the cached type forgenericTypeName.TypeNamewon't be set during the symbol resolving process for the second parsing.However, the type resolution in
TypeName.GetReflectionType()doesn't work for a generic type definition in most cases, for example, when the generic type expression is[System.Collections.Generic.List[string]],genericTypeName.TypeNamewill be aTypeNameinstance with the full nameSystem.Collections.Generic.Listwhich will fail to be resolved. That's why the second time you parse the same generic type expression,genericTypeName.TypeName.GetReflectionType()will return null.Why
genericTypeName.TypeNamecan be resolved in the first-time resolution ofgenericTypeName, but doesn't work when directly callinggenericTypeName.TypeName.GetReflectionType()? That's because for the former, withinVisitGenericTypeName(...), it uses aTypeResolutionStateinstance as the resolution context, which is constructed with the information from thegenericTypeName(seecode here). But when directly callinggenericTypeName.TypeName.GetReflectionType(), it doesn't have that information and thus cannot use the same/equivalentTypeResolutionStateinstance as the context for type resolution.The fix is to pass the generic argument count to
TypeNamewhen constructing aGenericTypeNameinstance, so that theTypeNameinstance can try resolving with an alternate name (i.e.typename`<n>) when the original name fails to resolve.The changes also fix another issue:
Before: assembly-qualified name
[System.Collections.Generic.List[string], System.Private.CoreLib]cannot be resolved.After:
[System.Collections.Generic.List[string], System.Private.CoreLib]can be resolved as expected.PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.- [ ] Issue filed: