UI Changes - Inline Parameter Name Hints#45800
UI Changes - Inline Parameter Name Hints#45800akhera99 merged 22 commits intodotnet:features/parameter-hintsfrom
Conversation
|
i'm feeling too sick to review now. but i will say, on a visual level alone, taht i think that looks really nice :) for those who don't know. We used some of the colors that |
…e of tags showing up when deleting them
To add to this, I used this website that Joey suggested which determines the ratio between the colors and made sure they meet the minimum for their respective themes. I also went ahead and made the hint slightly smaller so that it would look more floaty. |
I agree! This looks really good, and fits really well with how I would imagine using it, which is to most often be quickly toggling it on, and then off, for reference, but I think it also works for people who would want to leave it on permanently. |
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTaggerProvider.cs
Outdated
Show resolved
Hide resolved
| [Export] | ||
| [Name(InlineParameterNameHintsTag.TagId)] | ||
| [BaseDefinition(PredefinedClassificationTypeNames.FormalLanguage)] | ||
| internal ClassificationTypeDefinition InlineParameterNameHints; |
There was a problem hiding this comment.
What does this bit actually do? I had thought base definitions only mattered for which classification takes priority if a text span has multiple, and that wouldn't be applicable here.
There was a problem hiding this comment.
This is specifically for getting the IClassificationType in the Tagger. I need to essentially register the TagId I specified with the ClassificationTypeDefinition in order to do so.
There was a problem hiding this comment.
That would be on me. I asked Ankita to copy all the attributes because I couldn't remember what BaseDefinition was used for.
|
|
||
| namespace Microsoft.CodeAnalysis.Editor.InlineParameterNameHints | ||
| { | ||
| internal sealed class ClassificationTypeDefinitions |
There was a problem hiding this comment.
Class name doesn't match file name; file name looks better I think?
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
| _tagAggregator.TagsChanged += OnTagAggregatorTagsChanged; | ||
| } | ||
|
|
||
| private void OnClassificationFormatMappingChanged(object sender, EventArgs e) |
There was a problem hiding this comment.
This only runs on the UI thread?
There was a problem hiding this comment.
The assembly online says this Microsoft.VisualStudio.Text.UI.Wpf.dll, so I believe so
There was a problem hiding this comment.
we have ways of asserting this. it woudl be good for us to do that assertion so that if this ever turns out to be a wrong assumption we can get a crash immediately instead of a hard to figure out race condition.
| } | ||
|
|
||
| return tagsList; | ||
| return _cache; |
There was a problem hiding this comment.
We aren't filtering this to only the spans that were asked for? That can sometimes cause downstream surprises but if the editor is filtering them out right away then it's not too much of a concern.
| var fullSpan = new SnapshotSpan(snapshot, 0, snapshot.Length); | ||
| var requestSpans = new NormalizedSnapshotSpanCollection(fullSpan); | ||
| var dataTags = _tagAggregator.GetTags(requestSpans); |
There was a problem hiding this comment.
I recognize we're still investigating why this cache fixes the hang issue but if we merge this in let's file a tracking bug to not forget to remove this if we get distracted by other work. Making UI for all the tags on the UI thread even if they're not visible isn't great, but works for the short term.
There was a problem hiding this comment.
@jasonmalinowski is it possible the following is happening:
- we compute tags
- we report tags.
- editor calls into us to get tags and then displays them.
- displaying the tag causes the line to change (due to the adornment)
- we're listening to line changes and we kick off anotehr computation
rinse repeat?
There was a problem hiding this comment.
@CyrusNajmabadi We figure it's something like that, yeah. Displaying the tag will cause the editor to have to lay out the text again but that won't create a new snapshot or make our async tagger reprocess it. We chatted with the editor team and they were aware of one potential issue; the editor calls for tags twice during the process of laying everything out; and if between those two times you are replacing text with an adornment (which the editor supports, but we're not doing here) and you changed the tags between those two calls you might end up with extra layouts or bit of a cycle until things stabilize. But we're not using that editor feature, and our async tagger correctly raises tags changed on the UI thread, and only then reports new tags, so it looks like everything is fine there.
There was a problem hiding this comment.
The samples that the editor team have often use a cache of the adornment tags in general and we could bring that code into here; our original belief was because our async tagger wasn't doing the bad things the editor knew to avoid we thought we were good and didn't need a caching layer atop the async tagger's caching layer. @akhera99 is still investigating further and trying to narrow it down.
| var dataTags = _tagAggregator.GetTags(spans); | ||
| var snapshot = spans[0].Snapshot; | ||
| foreach (var tag in dataTags) | ||
| if (_cache.Count == 0 || snapshot != _cacheSnapshot) |
There was a problem hiding this comment.
So if the file has no spans, then we'll keep requerying the aggregator over and over again? Any concerns about performance or cache impacts there? I'm not sure if the cache needs to better distinguish "empty" versus "not cached".
There was a problem hiding this comment.
That's a good point. I will try to figure out a way to distinguish the cases.
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
That floaty look looks really good :) |
| VerticalAlignment = VerticalAlignment.Center, | ||
| FontStyle = FontStyles.Normal, | ||
| FontFamily = format.Typeface.FontFamily, | ||
| FontSize = format.FontRenderingEmSize - (0.25 * format.FontHintingEmSize), |
There was a problem hiding this comment.
doc. also, can you post some pictures at:
- different font sizes in the editor
- different fonts in the editor
- different zoom sizes in teh editor. (for example, i run at 137%)
- different DPI levels for windows?
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
| /// <summary> | ||
| /// _cache stores the parameter hint tags in a global location | ||
| /// </summary> | ||
| private readonly List<ITagSpan<IntraTextAdornmentTag>> _cache; |
There was a problem hiding this comment.
i'm still opposed to teh cache.
There was a problem hiding this comment.
regardless of the performance, I do think I will still need some sort of logic where the tagspans get stored globally because when the options change, I still need to clear that out and completely recreate them
There was a problem hiding this comment.
i would say you don't need to do that. intead, the way tagging works is you hook up "Event sources", i.e. things you're listening to taht should cause you to recompute tags. in your case, you'd have an event source listening for wahtever option this is to change, and then firing the appropraite "something changed" notification to retrigger tagging.
There was a problem hiding this comment.
See ITaggerEventSource and TaggerEventSources. We'll likely need a new source here, but it should hopefully not be hard to hook up and make work.
There was a problem hiding this comment.
I see, okay. I will look into it
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Show resolved
Hide resolved
| <value>(external)</value> | ||
| </data> | ||
| <data name="Inline_Parameter_Name_Hints" xml:space="preserve"> | ||
| <value>Inline Parameter Name Hints</value> |
There was a problem hiding this comment.
where is this disdplayed. Capital Case Is A Bit Weird versus Most UI string should be title cased.
|
Done with pass. |
|
So @akhera99 and I debugged into why that cache was preventing hangs. If we don't have a cache and re-create new FrameworkElement tag each time, what can happen is:
This causes the dispatcher queue to always be filled as we're requeuing layouts over and over again. The thing we don't understand yet is why the SizeChanged is being triggered; even if we do have the cache that probably means we're doing a bunch of extra layouts each time we add new adornments which isn't good even if we keep the cache in place. |
| [Export] | ||
| [Name(InlineParameterNameHintsTag.TagId)] | ||
| [BaseDefinition(PredefinedClassificationTypeNames.FormalLanguage)] | ||
| internal ClassificationTypeDefinition InlineParameterNameHints; |
There was a problem hiding this comment.
That would be on me. I asked Ankita to copy all the attributes because I couldn't remember what BaseDefinition was used for.
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
| </Color> | ||
| <Color Name="label name"> | ||
| </Color> | ||
| <Color Name="inline parameter name hints"> |
There was a problem hiding this comment.
Each file is its own self contained world, so they need to be defined in both places. If we wanted to say these colors are not going to be scheme-able we could move this to the VS EditorColors.xml. But really, I should finish the job of moving every Roslyn color into these schemes.
…ieve just the tags from the current view and not the entire file
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Outdated
Show resolved
Hide resolved
| VerticalAlignment = VerticalAlignment.Center, | ||
| FontStyle = FontStyles.Normal, | ||
| FontFamily = format.Typeface.FontFamily, | ||
| FontSize = format.FontRenderingEmSize - (0.25 * format.FontHintingEmSize), |
There was a problem hiding this comment.
Do we need to be setting both the height of the border and the height of the text? I would have imagined setting one was sufficient and the other would just resize accordingly.
There was a problem hiding this comment.
I remember reading somewhere that, when encased in a border, you need to have the border set the height in order for the sizing of the text to change relative to that height.
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/InlineParameterNameHints/InlineParameterNameHintsDataTaggerProvider.cs
Outdated
Show resolved
Hide resolved
| IClassificationFormatMapService classificationFormatMapService, | ||
| IClassificationTypeRegistryService classificationTypeRegistryService, | ||
| IThreadingContext threadingContext) |
There was a problem hiding this comment.
We're not using these, right? We can just delete?
There was a problem hiding this comment.
They're being used in the Tagger.

















Hello,
This is a PR for merging the UI changes I have made to the project. I am now putting the textblock within a border, so it has curved edges and looks to be more of a part of the editor. I also am now pulling from the Tools->Options->Fonts and Colors location in order to retrieve the font/font size of the editor so that the hints get updated from that. Also, there are now default colors for the hints in each theme which are also customizable.
The reason that this relies on the cache added in a separate PR is that when the format mapping changes, I now need to clear the cache so that they can be recreated with the changes made in the option page.
Here are samples from each IDE theme-
Light:

Blue:

Blue (Extra Contrast):

Dark:

Please let me know what you guys think!
@JoeRobich PTAL