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 TypeName APIs to simplify metadata lookup. #111598

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

teo-tsirpanis
Copy link
Contributor

Fixes #101774.

Tests for Unescape TBA.

Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jan 20, 2025
return input;
}

ValueStringBuilder builder = new(stackalloc char[128]);
Copy link
Member

Choose a reason for hiding this comment

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

stackalloc is relatively expensive when it is not reachable. It should be in the helper method too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@jkotas
Copy link
Member

jkotas commented Jan 20, 2025

Could you please delete

<Compile Include="$(CommonPath)System\Reflection\Metadata\TypeNameHelpers.cs">
<Link>Common\System\Reflection\Metadata\TypeNameHelpers.cs</Link>
</Compile>
and replace the calls to it with this API?

(Other uses of TypeNameHelpers.cs should be delete too once these APIs are available in the LKG runtime.)

}
builder.Append(input.Slice(0, indexOfEscapeChar));
int indexOfNextChar = indexOfEscapeChar + 1;
if (indexOfNextChar < input.Length && input[indexOfNextChar] is char c && NeedsEscaping(c))
Copy link
Member

Choose a reason for hiding this comment

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

You should not need to call NeedsEscaping here. Take a look how the existing Unescape helper in TypeNameHelpers.cs is implemented.

Copy link
Member

Choose a reason for hiding this comment

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

Given that this is very rare case, it is better to keep the implementation as simple as possible - the existing Unescape helper in TypeNameHelpers.cs that processes one character at a time looks simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copied implementation from TypeNameHelpers.cs, removed it and updated usages.

/// </summary>
/// <param name="name">The input string containing the name to convert.</param>
/// <returns>A string of characters with any escaped characters converted to their unescaped form.</returns>
/// <remarks>The unescaped string can be used for looking up the type name or namespace in metadata.</remarks>
Copy link
Member

Choose a reason for hiding this comment

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

Also mention that the API does not validate that the escape sequences are only used for characters that require escaping?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@@ -13,13 +13,14 @@ namespace System.Reflection.Metadata.Tests
public class TypeNameTests
Copy link
Member

@jkotas jkotas Jan 20, 2025

Choose a reason for hiding this comment

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

Is there test coverage for parsing a nested types with namespace e.g. TypeName.Parse("a.b+c.d")?

What is TypeName.Parse("a.b+c.d").Namespace going to return?

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 guess it will return a.b+c which is obviously wrong. I didn't know this syntax is supported, TIL!

I think it should return a, because the reflection APIs seem to ignore the namespace in the nested type. Passing System.Collections.Generic.Dictionary`2+MyRandomNamespace.Enumerator to Type.GetType returns the expected result, while if I flip the namespaces it returns null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to return a in your example.

Copy link
Member

Choose a reason for hiding this comment

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

Passing System.Collections.Generic.Dictionary`2+MyRandomNamespace.Enumerator to Type.GetType returns the expected result

.NET Framework throws exception in this case. This looks like a bug in .NET Core - regression introduced by rewrite of the type name parser in C#. I do not think that the parser should be silently dropping any significant part of the input to the floor.

Updated to return a in your example.

I think that the behavior for my example should be:

  • Namespace returns "c", Name returns "d"
    or
  • Namespace returns empty string, Name returns "c.d"

@teo-tsirpanis teo-tsirpanis requested a review from Copilot January 20, 2025 22:15

Choose a reason for hiding this comment

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

Copilot reviewed 5 out of 17 changed files in this pull request and generated no comments.

Files not reviewed (12)
  • src/coreclr/tools/ILVerification/ILVerification.projitems: Language not supported
  • src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj: Language not supported
  • src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj: Language not supported
  • src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems: Language not supported
  • src/tools/illink/src/linker/Mono.Linker.csproj: Language not supported
  • src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs: Evaluated as low risk
  • src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs: Evaluated as low risk
  • src/tools/illink/src/linker/Linker/TypeNameResolver.cs: Evaluated as low risk
  • src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs: Evaluated as low risk
  • src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs: Evaluated as low risk
  • src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs: Evaluated as low risk
  • src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs: Evaluated as low risk
@teo-tsirpanis teo-tsirpanis force-pushed the typename-namespace-unescape branch from e1a9730 to d08be6b Compare January 20, 2025 22:19
@teo-tsirpanis teo-tsirpanis force-pushed the typename-namespace-unescape branch from d08be6b to 1e3f969 Compare January 20, 2025 22:30
@teo-tsirpanis teo-tsirpanis force-pushed the typename-namespace-unescape branch from 1e8ddbf to e5ecca6 Compare January 20, 2025 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[API Proposal]: Simplify lookup of parsed TypeName in metadata
2 participants