-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Improve the signature display when a tuple appears many times within it. #56025
Improve the signature display when a tuple appears many times within it. #56025
Conversation
@@ -517,6 +517,12 @@ private void AddTupleTypeName(INamedTypeSymbol symbol) | |||
{ | |||
Debug.Assert(symbol.IsTupleType); | |||
|
|||
if (this.format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.DoNotExpandTupleType)) | |||
{ | |||
builder.Add(CreatePart(SymbolDisplayPartKind.StructName, symbol, "<tuple>")); |
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 is similar to what we do with anonymous types. With anon-types, the compiler just makes a single part, allowing the IDE control of how to build the final display string. For tuples it's fine (by default) to expand it as (...)
, but we need a way to have that not happen in order to use the new display logic.
@@ -534,7 +540,7 @@ private void AddTupleTypeName(INamedTypeSymbol symbol) | |||
if (element.IsExplicitlyNamedTupleElement) | |||
{ | |||
AddSpace(); | |||
builder.Add(CreatePart(SymbolDisplayPartKind.FieldName, symbol, element.Name)); | |||
builder.Add(CreatePart(SymbolDisplayPartKind.FieldName, element, element.Name)); |
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 was a bug before (we were adding in the tuple again for each tuple element). This caused problems with the IDE code as we'd then try to expand these references out as well.
/// Insert a tuple into the display parts as a single part instead of multiple parts (similar | ||
/// to how anonymous types are inserted0. | ||
/// </summary> | ||
DoNotExpandTupleType = 1 << 9, |
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.
open to discussing a good name here. We use the term 'expand' in other places (like 'ExpandNullable'). Maybe DoNotExpandTuples?
{ | ||
$$M(default); | ||
}", | ||
MainDescription(@"void C.M((int x, string y) t)"), |
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.
in the single use case, we keep the signature as before.
[ExportLanguageService(typeof(IAnonymousTypeDisplayService), LanguageNames.CSharp), Shared] | ||
internal class CSharpAnonymousTypeDisplayService : AbstractAnonymousTypeDisplayService | ||
[ExportLanguageService(typeof(IStructuralTypeDisplayService), LanguageNames.CSharp), Shared] | ||
internal class CSharpStructuralTypeDisplayService : AbstractStructuralTypeDisplayService |
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.
most of the code changes are a strictly mechanical change of 'AnonymousType' => 'StructuralType'. I'll mark which parts of the code are actually changed.
@@ -1,176 +0,0 @@ | |||
// Licensed to the .NET Foundation under one or more agreements. |
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 type was not deleted. but enough changed happened to it that github considers it a rewrite.
orderAndCount.count++; | ||
_namedTypes[symbol] = orderAndCount; | ||
return; | ||
} |
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 is new logic.
else | ||
{ | ||
typeParts.AddRange(GetTypeParts(structuralType, semanticModel, position)); | ||
} |
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 part is new.
|
||
private static ImmutableArray<INamedTypeSymbol> GetTransitiveStructuralTypeReferences( | ||
ImmutableArray<INamedTypeSymbol> structuralTypes) | ||
{ |
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 method has been rewritten.
IDictionary<INamedTypeSymbol, string> structuralTypeToName, | ||
SemanticModel semanticModel, | ||
int position) | ||
{ |
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 method was rewritten.
|
||
restart: |
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 loop moved into StructuralTypeDisplayInfo.ReplaceStructuralTypes
I was expecting this to be a new section on the tool tip. Did it get too long with a new section, or do you just consider them the same? And if so, how much is that your compiler-dev brain at work? :) "Structural types" doesn't have much meaning to me, though I'm not exactly against it, as it I can work out what it means. Mainly just surprised, especially if adding delegate info is going to give us a new section here anyway. |
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.
Another random thought, is it worth using 't
for tuples to distinguish them?
{ | ||
if (namedType.IsTupleType && count == 1) | ||
{ | ||
// Ignore tuples only referenced once. We'll keep them inline. If the tuple shows up multiple times, |
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.
I wonder if this should only apply if there isn't otherwise going to be a "Structural Types" section? eg, what happens in this case:
public (int a, int b) Goo((int a, int b), (string x, string y);
You're going to end up with a "Structural Types" section that doesn't list out all of the structural types.
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.
That's an interesting point. I could revise to make it that once we have at least one duplicated tuple that all tuples then are broken out... That seems reasonable to me.
I just didn't think this warranted a new section. To me each section is very distinct in it's purpose. If we added a new section it would effectively be done the exact same as the existing anonymous type section. Because of that, I just washed one section that showed you all the type expansions in a single place. |
I would definitely put delegates into this section, and I had that in mind when writing this :-) |
You're right. I think that can just simplify to |
Possibly. Are you thinking |
Nevermind, ignore me. I always assumed the "a" in |
@CyrusNajmabadi I don't think this requires a full session, but can you please send an email to the api design alias with the proposal? |
On it. |
@333fred renamed to CollapseTupleTypes |
@dotnet/roslyn-compiler for small public API change to enhance SymbolDisplay. |
@dotnet/roslyn-compiler @333fred for eyes on the SymbolDisplay change. |
8e58534
to
8e663dd
Compare
Rebasing to 17.1 |
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.
Symbol display change LGTM
@jcouv can you ptal? |
/// Insert a tuple into the display parts as a single part instead of multiple parts (similar | ||
/// to how anonymous types are inserted). | ||
/// </summary> | ||
CollapseTupleTypes = 1 << 9, |
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.
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.
Primarily because they are structural types that require a lot more than a name to reference. For example, when you have a nominal type, it doesn't matter how many members that type has, you just reference it by name. Hit with a structural type you have to include that structure in somehow.
If we have more cases like that in the future, I'd expect we go down a similar route.
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.
when you have a nominal type, it doesn't matter how many members that type has, you just reference it by name
But the nominal type could be arbitrarily complicated, for instance Dictionary<string, object>
.
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.
Potentially. We haven't had that arise as significant enough to need attention. If we did though, I'd prefer that as a separate flag.
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.
Compiler change LGTM Thanks (iteration 34). I take Fred's sign-off as evidence of sufficient public API discussion.
Fixes #29949
Fixes #53061
Fixes #33609
Similar to what we do with anonymous types, we'll now show tuples like so (when they appear at least two times in a signature).
Before:
After: