Improve the signature display when a tuple appears many times within it.#56025
Conversation
|
|
||
| if (this.format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.DoNotExpandTupleType)) | ||
| { | ||
| builder.Add(CreatePart(SymbolDisplayPartKind.StructName, symbol, "<tuple>")); |
There was a problem hiding this comment.
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.
| { | ||
| AddSpace(); | ||
| builder.Add(CreatePart(SymbolDisplayPartKind.FieldName, symbol, element.Name)); | ||
| builder.Add(CreatePart(SymbolDisplayPartKind.FieldName, element, element.Name)); |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
this is new logic.
| else | ||
| { | ||
| typeParts.AddRange(GetTypeParts(structuralType, semanticModel, position)); | ||
| } |
There was a problem hiding this comment.
this part is new.
|
|
||
| private static ImmutableArray<INamedTypeSymbol> GetTransitiveStructuralTypeReferences( | ||
| ImmutableArray<INamedTypeSymbol> structuralTypes) | ||
| { |
There was a problem hiding this comment.
this method has been rewritten.
| IDictionary<INamedTypeSymbol, string> structuralTypeToName, | ||
| SemanticModel semanticModel, | ||
| int position) | ||
| { |
There was a problem hiding this comment.
this method was rewritten.
| info.AnonymousTypesParts); | ||
| AddToGroup(SymbolDescriptionGroups.StructuralTypes, info.TypesParts); | ||
|
|
||
| restart: |
There was a problem hiding this comment.
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. |
davidwengier
left a comment
There was a problem hiding this comment.
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.
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.
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 |
|
@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.
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.
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.
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.
jcouv
left a comment
There was a problem hiding this comment.
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: