-
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
Add support for displaying reference kind in Find All References window. #30155
Conversation
Implementation of the custom column support has been kept extensible, so that each reference item can have customized key-values info, where key corresponds to the name of the custom dynamic column and values are set of one or more values the table entry. Columns become dynamically visible if at least one row in the table has a value for it. Fixes dotnet#24877
/// This entry indicates that the reference has additional value usage information which indicate | ||
/// it is a read/write reference, such as say 'a++'. | ||
/// </summary> | ||
public ImmutableDictionary<string, ImmutableArray<string>> ReferenceInfo { get; } |
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 believe this type will held in memory until find all reference window get cleared. so, might be good to not create new dictionary with same vaules again and again? but re-use dictionary with same values. #Resolved
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 agree with heejae. Also, i think we already have a MultiDictionary. We should probably just use that. #Resolved
ReferenceInfo = referenceInfo ?? throw new ArgumentNullException(nameof(referenceInfo)); | ||
} | ||
|
||
internal SourceReferenceItem(DefinitionItem definition, DocumentSpan sourceSpan, ValueUsageInfo valueUsageInfo) |
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.
how about having ctro that contains both isWrittenTo and ReferenceInfo as parameter? #ByDesign
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 have maked the the ctor with IsWrittenTo as obsolete. @CyrusNajmabadi told me that TS uses it, so I did not remove it. Hopefully they can move to new ctor and then we can completely remove IsWrittenTo and obsolete ctor. #ByDesign
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.
Note: i'm not certain if they use it. might as well check. if tehy don't, def just remove :) #Resolved
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.
Verified that TypeScript does still use the constructor public SourceReferenceItem(DefinitionItem definition, DocumentSpan sourceSpan, bool isWrittenTo)
. I am going to retain the existing approach.
In reply to: 220759901 [](ancestors = 220759901)
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.
on the fence about ValueUsageInfo being baked into this API directly. I think i'd prefer if it just took a MultiDictionary<string, string> ReferenceInfo
as an argument instead.
Other minor note: Is MultiDictionary mutable? If so... i may have to retract my position about using it since we'd want immutable data here. If it is immutbale, great! #Resolved
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.
Is MultiDictionary mutable
Yes, it is. I will revert it back to ImmutableDictionary<string, ImmutableArray<string>>
. #Resolved
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.
Darn... sorry about that :(
#Resolved
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.
We invoke this from multiple places and we are caching the mapping from ValueUsageInfo to the reference info values map here, so for now I will retain this here.
In reply to: 222055535 [](ancestors = 222055535)
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.
{ | ||
var referenceInfo = ImmutableDictionary<string, ImmutableArray<string>>.Empty; | ||
|
||
var values = valueUsageInfo.ToValues(); |
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.
here, you might have some cache to reuse existing dictionary? or most common one? or like last 10 unique ones? something like that. #Resolved
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.
Sure. #Resolved
/// </summary> | ||
internal abstract class AbstractFindUsagesCustomColumnDefinition : TableColumnDefinitionBase | ||
{ | ||
protected AbstractFindUsagesCustomColumnDefinition() |
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.
tagging @olegtk for eyes from editor team. I can't find github alias for david pugh. #Pending
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.
Thanks, yes confirmation from Oleg and David will help. By the way, I verified that just defining a new column with export attribute doesn't cause it to be automatically displayed in FAR window even for us. Platform code explicitly adds only the fixed column set and any variable column has to be explicitly added using the TableControl.SetControlStates
API. #Resolved
/// </summary> | ||
[Export(typeof(ITableColumnDefinition))] | ||
[Name(ColumnName)] | ||
internal sealed class FindUsagesValueUsageInfoColumnDefinition : AbstractFindUsagesCustomColumnDefinition |
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.
@olegtk so this will not load roslyn when like C++ do find all references? right? #Pending
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.
Definitely need to figure this out as well. #Resolved
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.
The column doesn't seem to show unless explicitly added to the table control. MEF-exporting just seems to add it to the table column definition manager.
In reply to: 222372310 [](ancestors = 222372310)
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.
It's still not clear to me though when it is MEF imported. If it is imported even when C#/VB haven't been loaded... then that's not good :-/
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.
@@ -171,8 +172,9 @@ private static bool IsForEachProperty(IPropertySymbol symbol) | |||
} | |||
|
|||
var location = argumentList.SyntaxTree.GetLocation(new TextSpan(argumentList.SpanStart, 0)); | |||
var valueUsageInfo = semanticModel.GetValueUsageInfo(node, semanticFacts, cancellationToken); |
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.
curious, why semanticFacts is needed? #ByDesign
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.
It will not be needed once #30123 is merged. For now, we use it for bunch of helpers. #Resolved
@@ -501,8 +504,9 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) | |||
if (deconstructMethods.Any(m => Matches(m, originalUnreducedSymbolDefinition))) | |||
{ | |||
var location = syntaxFacts.GetDeconstructionReferenceLocation(node); | |||
var valueUsageInfo = semanticModel.GetValueUsageInfo(node, semanticFacts, cancellationToken); |
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.
it has document. so might make sense to have exteion method on document then? document.GetValueUsageIfoAsync(node, cancellation)? rahter than one to retrieve things and then call on semanticmodel?
just nit thing since feels like it can save typing. #ByDesign
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 added it on SemanticModel based on @CyrusNajmabadi suggestion here. Eventually it should probably go into the compiler layer. #Resolved
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.
yes. i would prefer tihs be on semanticmodel. #Resolved
|
||
// After adding us as the source, the manager should immediately call into us to | ||
// tell us what the data sink is. | ||
Debug.Assert(_tableDataSink != null); | ||
|
||
// Initialize and update custom column states. | ||
_customColumnStatesMap = GetInitialCustomColumnStates(findReferencesWindow.TableControl.ColumnStates, customColumns, customColumnNames); |
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.
so mostly work is just adding this custom column to table control. so, review from editor team will be helpful @olegtk #Pending
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.
Yes. I also need their help for the TODO (2) mentioned in PR description. Let me start an internal thread with them. #Pending
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.
feels super weird to pass two sets along here. DOes hte GetInitialCustomColumnStates code assume anything about hte relation of their order? #Resolved
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.
Passing the columnNames set as there is a contains check in it. I can also refactor to pass a single set. #Resolved
} | ||
|
||
return base.TryGetFilterItems(entry, out filterItems); | ||
} |
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.
- what does this method do? #Resolved
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 basically determines the constituent strings for the display value in column, which should be used for applying the filter. For example, value "Read, Write" displayed in column for an entry, we will return "Read" and "Write" here, so filtering based on individual filter terms can be done. #Resolved
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.
|
||
// Default implementation for column display value. | ||
public virtual string GetDisplayStringForColumnValues(ImmutableArray<string> values) => string.Join(", ", values); | ||
protected virtual IEnumerable<string> SplitColumnDisplayValue(string displayValue) => displayValue.Split(',').Select(v => v.Trim()); |
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'm concerned about this all being allocation heavy. do we do this once per item? Or just once per column/window? if it's per item, we should cache the results since tehre will likely only ever be a handful of actual distinct instances. #Resolved
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.
Sure, I can optimize here as we have fixed set of combinations. #Resolved
/// <summary> | ||
/// Column states for custom columns. | ||
/// </summary> | ||
private readonly Dictionary<string, ColumnState2> _customColumnStatesMap; | ||
#endregion |
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.
nit: blank line above #endregion. #Resolved
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.
just to be clear. You want this in this region right? i.e. this is intended ot be protected by _gate? if so, great. but i just want to check. #Resolved
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.
Yes, correct - it currently has all uses protected by _gate.
In reply to: 222056491 [](ancestors = 222056491)
/// <summary> | ||
/// Column states for custom columns. | ||
/// </summary> | ||
private readonly Dictionary<string, ColumnState2> _customColumnStatesMap; |
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.
Update docs (or name) to say what hte mapping is to/from. i don't know what this string actually is here. maybe columnTitleToStateMap? (if it is the title... just guessing here). #Resolved
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.
columnTitleToStateMap? (if it is the title... just guessing here).
That is correct. Will change #Resolved
#endregion | ||
|
||
protected AbstractTableDataSourceFindUsagesContext( | ||
StreamingFindUsagesPresenter presenter, | ||
IFindAllReferencesWindow findReferencesWindow) | ||
IFindAllReferencesWindow findReferencesWindow, | ||
ImmutableHashSet<AbstractFindUsagesCustomColumnDefinition> customColumns) |
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.
surprised this is a HashSet. any reason for that versus just an array? when i see 'set' it makes me thing "we'll have duplicates, and we need to make them unique." But it's unclear to me why we'd have multiple copies of the same column. #Resolved
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.
Yes, will change to immutable array. #Resolved
|
||
// Initialize and update custom column states. | ||
_customColumnStatesMap = GetInitialCustomColumnStates(findReferencesWindow.TableControl.ColumnStates, customColumns, customColumnNames); | ||
TableControl.SetColumnStates(_customColumnStatesMap.Values); |
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.
.values will be unordered here. is that what we want? if there are multiple columns, we could get non-deterministic ordering behavior now/in-the-future. #Resolved
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 don't know if SetColumnStates
can affect column ordering or just affects the state. @olegtk? #Resolved
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 confirmed by looking at the editor code that order of the input column states is irrelevant for SetColumnStates
.
In reply to: 220752779 [](ancestors = 220752779)
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.
{ | ||
var customColumnStatesMap = new Dictionary<string, ColumnState2>(customColumnNames.Count); | ||
|
||
// If there is an existing column state for the custom column, flip it to be non-visible by default. |
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.
why...? #Resolved
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.
The column will be completely empty for FAR on things such as types, literals, methods, no references found case, etc. Current implementation dynamically changes the column visibility based on whether at least one entry has a non-default value, and it seems to work pretty well. I can provide a gif animation for the experience here. #Resolved
@@ -267,7 +306,8 @@ protected async Task<(Guid, string projectName, SourceText)> GetGuidAndProjectNa | |||
protected async Task<Entry> CreateDocumentSpanEntryAsync( | |||
RoslynDefinitionBucket definitionBucket, | |||
DocumentSpan documentSpan, | |||
HighlightSpanKind spanKind) | |||
HighlightSpanKind spanKind, | |||
ImmutableDictionary<string, ImmutableArray<string>> customColumnsDataOpt = null) |
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.
Ideally, avoid optional params in internal code. It makes it too easy to miss a case when someone should not get the default, and doesn't know they need to pass this along. #Resolved
projectName, guid, sourceText, classifiedSpansAndHighlightSpan, GetAggregatedCustomColumnsData()); | ||
|
||
// Local functions. | ||
ImmutableDictionary<string, string> GetAggregatedCustomColumnsData() |
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.
not certain what this is actually returning... what are the keys, whare the expected values? It's not clear what 'aggregated' means here. #Resolved
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.
It's basically aggregating values. For example:
{
{ "Column1", {"Value1", "Value2"} },
{ "Column2", {"Value3", "Value4"} }
}
will transform to:
{
{ "Column1", "Value1, Value2" },
{ "Column2", "Value3, Value4" }
}
``` #Resolved
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.
ok. doc comment then :) #Resolved
// Update the column states if required. | ||
if (newColumnStatesOpt != null) | ||
{ | ||
TableControl.SetColumnStates(newColumnStatesOpt); |
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.
- is this safe on the BG thread?
- You might be hearing about this from multiple threads simultaneously (find-refs is heavily multi-threaded). Is this safe? #Resolved
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.
@olegtk? #Resolved
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 just verified from looking at Editor layer code that this API forces switch to UI thread, so it should be safe to call here. Also note that we will call it only once for each new custom column to add for each FAR query - the lock above this guarantees that newColumnStatesOpt
is going to be non-null only for the first FAR result that has a non-empty column value. #Resolved
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.
great. consider doc'ing that to help make it clear this is all intentional and safe. thanks! #Resolved
.Cast<ValueUsageInfo>() | ||
.Where(value => value != ValueUsageInfo.None && (value & (value - 1)) == 0) // Single bit set | ||
.Select(v => v.ToString()) | ||
.ToImmutableArray(); |
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.
it's unclear to me what the localization concerns are here. Are these filters shown to the user? If so, we likely cna't use v.toString here and we need to actually provide appropriate localized values depending on the enum value. #Pending
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.
Yes, the values here are directly from the ValueUsageInfo enum. We either need to define corresponding string constants or localizable resource strings here to display in FAR column. #Pending
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.
gotcha. as a WIP this is fine then :) #Pending
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 pending design issue, which will be addressed once we finalize the design: allowable values in this column AND localizable or not.
In reply to: 220755788 [](ancestors = 220755788)
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.
Cute! #Resolved
@@ -1069,4 +1069,7 @@ I agree to all of the foregoing:</value> | |||
<data name="Prefer_compound_assignments" xml:space="preserve"> | |||
<value>Prefer compound assignments</value> | |||
</data> | |||
<data name="Kind" xml:space="preserve"> | |||
<value>Kind</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.
probably needs a localization note. this is pretty vague :) #Pending
} | ||
} | ||
|
||
return builder.ToImmutable(); |
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.
it would probably be very good to cache this. Also, is this passed back to the editor as an interface type (like IList/IReadOnlyList?). If so, we should cache in that form so we don't box on converting the immutablearray to the interface. #Resolved
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 now cached in the FAR column which invokes this method.
In reply to: 220754589 [](ancestors = 220754589)
@@ -50,14 +56,14 @@ public struct ReferenceLocation : IComparable<ReferenceLocation>, IEquatable<Ref | |||
|
|||
public CandidateReason CandidateReason { get; } | |||
|
|||
internal ReferenceLocation(Document document, IAliasSymbol alias, Location location, bool isImplicit, bool isWrittenTo, CandidateReason candidateReason) | |||
internal ReferenceLocation(Document document, IAliasSymbol alias, Location location, bool isImplicit, ValueUsageInfo valueUsageInfo, CandidateReason candidateReason) |
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 may be called from another language (not sure, but we need to check). If so, we might need to leave the old constructor, and have it delegate to a new one.
However, if this is truly C#/VB only, then this is safe. i just dont remember anymore. #Resolved
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 SemanticModel semanticModel, | ||
SyntaxNode node, | ||
ISemanticFactsService semanticFacts, | ||
CancellationToken cancellationToken) |
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.
did this move from somewhere? #Resolved
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.
ok great. let's track that in #30123 if you're not already doing that :) #Resolved
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.
Done with first pass. Other notes from the original post:
Yes. |
If we do this, let' make sure that the column does nto disappear/reappear as you scroll. Once the column is there, it should just stay there. #Resolved |
} | ||
else if (operation.Parent is INameOfOperation || | ||
operation.Parent is ITypeOfOperation || | ||
operation.Parent is ISizeOfOperation) | ||
{ | ||
return ValueUsageInfo.NonReadWriteRef; | ||
return ValueUsageInfo.NameReference; |
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.
not a huge fan of th ename. but it's also likely good/clear enough, so i'm not bothered enough to want it changed :) #Resolved
/// </summary> | ||
WritableRef = 0x01000, | ||
Reference = 0x0100, |
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.
nice. i like this more. #Resolved
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.
@jasonmalinowski's suggestion :) #Resolved
/// For example, 'nameof(x)' does not read or write the underlying value stored in 'x'. | ||
/// </summary> | ||
NonReadWriteRef = 0x10000, | ||
NameReference = 0x1000, |
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 one doesn't really fit now since it uses 'Reference' in the name, but isn't or'ed with 'Reference'. I would be ok with ValueUsage.NameOnly perhaps #Resolved
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.
or maybe 'AsName', or maybe 'NotAsValue'. #Resolved
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.
Seems reasonable, and felt little odd to me too. I am going to make your suggested change to use NameOnly
#Resolved
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.
Going to stick with NameOnly
for now and we can make the resource string change later if we feel it is still confusing.
In reply to: 222061219 [](ancestors = 222061219)
@@ -747,4 +747,16 @@ | |||
<data name="Refactoring_Only" xml:space="preserve"> | |||
<value>Refactoring Only</value> | |||
</data> | |||
<data name="NameReference" xml:space="preserve"> | |||
<value>NameReference</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.
this is a strange resource name. is it just pending something better? :) #Resolved
Wow. This was super clean. I really really like how it came out. All my comments are basic nits, or general questoins i just want to get clarity around. It actually looks like there shouldn't be any concerns, but i want to double-check some things. Once i hear back, i can sign off asap! Thanks! |
Also paging @jnm2 as i think he'll be really happy to see this :) |
That is the secondary issue. The actual failure is above that running tests. Mono is crashing running one of the assemblies. This is a known issue and I have a PR out to Short term just rerun the VSTS build |
@jaredpar I have tried to requeue the build few times, but it still fails the Linux Mono test. |
@mavasani sigh, now it's failing for a different reason: docker zombie container 😦 This is an issue I'm working with AzDev on. Let me know when you're ready to merge and I'll override the checks. |
Thanks @jaredpar. @CyrusNajmabadi any more concerns/feedback? We can merge once Cyrus sign's off. |
@mavasani Will do one more pass to make sure everything looks good :) |
|
||
namespace Microsoft.CodeAnalysis.FindUsages | ||
{ | ||
using ReferenceInfoMap = ImmutableDictionary<string, ImmutableArray<string>>; |
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 like this for now. If we ever open this stuff up though, we'll likely want to create a new type for this. #Pending
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.
} | ||
|
||
private static ReferenceInfoMap GetOrCreateReferenceInfo(ValueUsageInfo valueUsageInfo) | ||
=> s_valueUsageInfoToReferenceInfoMap.GetOrAdd(valueUsageInfo, CreateReferenceInfo); |
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 can't remember. will this cache the dleegate for CreateReferenceInfo? I don't think it will. So we can either fix this to explicitly cache that delegate, or switch to a simple lambda that calls the function (since hte compiler will cache htat). #Resolved
@@ -299,7 +299,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid | |||
} | |||
|
|||
// Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not. | |||
var rule = !valueUsageInfo.ContainsWriteOrWritableRef() && !valueUsageInfo.ContainsNonReadWriteRef() && !symbolsReferencedInDocComments.Contains(member) | |||
var rule = !valueUsageInfo.IsWrittenTo() && !valueUsageInfo.IsNameOnly() && !symbolsReferencedInDocComments.Contains(member) |
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 much prefer these new name! :) #Resolved
|
||
// Local functions. | ||
AbstractFindUsagesCustomColumnDefinition GetCustomColumn(string columnName) | ||
=> (AbstractFindUsagesCustomColumnDefinition)TableControl.ColumnDefinitionManager.GetColumnDefinition(columnName); |
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 assume this cast is always safe? i have'nt been able to convince myself it is. what if some other feature/language already made this column? #Resolved
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.
Valid point. I will filter out the key-value pairs for such cases.
In reply to: 222371741 [](ancestors = 222371741)
// Also note that we will call it only once for each new custom column to add for | ||
// each find references query - the lock above guarantees that newColumnStatesOpt is | ||
// going to be non-null only for the first result that has a non-empty column value. | ||
TableControl.SetColumnStates(newColumnStates); |
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.
note: this is only safe if SetColumnStates doesn't hold onto newColumnStates. i was thnking there would still be a .ToImmutable here. #Resolved
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.
// Allow filtering of the column by each ValueUsageInfo kind. | ||
private static readonly ImmutableArray<string> s_defaultFilters = Enum.GetValues(typeof(ValueUsageInfo)) | ||
.Cast<ValueUsageInfo>() | ||
.Where(value => value != ValueUsageInfo.None && value.IsSingleBitSet()) |
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.
value != ValueUsageInfo.None
seems redundant since you check IsSingleBitSet. #Resolved
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. Minor concerns. Feel free to fix or not if you want. I do think we need to ensure we don't load Roslyn unintentionally in non-Roslyn scenarios.
Implementation of the custom column support has been kept extensible, so that each reference item can have customized key-values info, where key corresponds to the name of the custom dynamic column and values are set of one or more values the table entry. Columns become dynamically visible if at least one row in the table has a value for it.
Fixes #24877
TODOs: