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 support for displaying reference kind in Find All References window. #30155

Merged
merged 8 commits into from
Oct 3, 2018

Conversation

mavasani
Copy link
Contributor

image

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:

  1. Finalize localization and terminology for the reference kinds (will need design review): Do we need to use localizable resource strings? Should the values be lot more succinct (like 'ref', 'out', 'in' 'read', 'write', etc.) or current descriptive terms are preferred?
  2. The new column does not show up in the visible part of the FAR window by default, and user needs to scroll and move the column for visibility (see image below). This seems to be due to the fact that underlying table control does not refresh/update the column widths when a dynamic column becomes visible. I will follow up with the platform team to ensure the default view shows the custom columns, whenever marked visible.

image

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
@mavasani mavasani added Area-IDE Need Design Review The end user experience design needs to be reviewed and approved. labels Sep 26, 2018
@mavasani mavasani requested review from CyrusNajmabadi and a team September 26, 2018 21:14
/// 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; }
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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)
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 27, 2018

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

Copy link
Contributor Author

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)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

@mavasani mavasani Oct 2, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No issues :) moved back to ImmutableDictionary.


In reply to: 222063382 [](ancestors = 222063382)

{
var referenceInfo = ImmutableDictionary<string, ImmutableArray<string>>.Empty;

var values = valueUsageInfo.ToValues();
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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()
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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

Copy link
Contributor Author

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)

Copy link
Member

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 :-/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, get your point. Probably @olegtk can answer that. Note that our approach is same as what C++ itself has been using for it's custom read/write column, which has been in place for at least a release.


In reply to: 222384111 [](ancestors = 222384111)

@@ -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);
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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);
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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);
Copy link
Contributor

@heejaechang heejaechang Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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);
}
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

Choose a reason for hiding this comment

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

  1. what does this method do? #Resolved

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added comment


In reply to: 220752126 [](ancestors = 220752126)


// 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());
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

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;
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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);
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

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 confirmed by looking at the editor code that order of the input column states is irrelevant for SetColumnStates.


In reply to: 220752779 [](ancestors = 220752779)

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 will add a comment.


In reply to: 221027314 [](ancestors = 221027314,220752779)

{
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.
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

Choose a reason for hiding this comment

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

why...? #Resolved

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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()
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 27, 2018

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);
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

Choose a reason for hiding this comment

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

  1. is this safe on the BG thread?
  2. You might be hearing about this from multiple threads simultaneously (find-refs is heavily multi-threaded). Is this safe? #Resolved

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

Choose a reason for hiding this comment

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

@olegtk? #Resolved

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 27, 2018

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();
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

@mavasani mavasani Sep 26, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 27, 2018

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

Copy link
Contributor Author

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)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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>
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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();
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

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)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Verified this is only used within Roslyn.sln.


In reply to: 220754806 [](ancestors = 220754806)

this SemanticModel semanticModel,
SyntaxNode node,
ISemanticFactsService semanticFacts,
CancellationToken cancellationToken)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Sep 26, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it was added here so we don't need to track multiple boolean flags. Additionally, I am hoping that this method will completely go away soon when we merge in #30123


In reply to: 220754879 [](ancestors = 220754879)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added comment #30123 (comment)


In reply to: 222061927 [](ancestors = 222061927)

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Sep 26, 2018

Done with first pass. Other notes from the original post:

Should the values be lot more succinct (like 'ref', 'out', 'in' 'read', 'write', etc.) or current descriptive terms are preferred?

Yes. Read, Write and Read/Write are likely the max complexity we should expose here. For things like nameof(...) it should just be nothing. #Resolved

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Sep 26, 2018

The new column does not show up in the visible part of the FAR window by default, and user needs to scroll and move the column for visibility (see image below). This seems to be due to the fact that underlying table control does not refresh/update the column widths when a dynamic column becomes visible. I will follow up with the platform team to ensure the default view shows the custom columns, whenever marked visible.

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;
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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,
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

@mavasani mavasani Oct 2, 2018

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,
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

Copy link
Contributor Author

@mavasani mavasani Oct 2, 2018

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

Copy link
Contributor Author

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>
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 2, 2018

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

@CyrusNajmabadi
Copy link
Member

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!

@CyrusNajmabadi
Copy link
Member

Also paging @jnm2 as i think he'll be really happy to see this :)

@mavasani
Copy link
Contributor Author

mavasani commented Oct 2, 2018

image

@mavasani
Copy link
Contributor Author

mavasani commented Oct 3, 2018

@dotnet/roslyn-infrastructure @jaredpar Seems Linux_Test mono is failing roslyn-ci with the following publish error:

Publishing build artifacts failed with an error: Not found PathtoPublish: /data/agent/_work/9/s/Binaries/$(_configuration)/Logs

@jaredpar
Copy link
Member

jaredpar commented Oct 3, 2018

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
Move to a newer mono that fixes this.

Short term just rerun the VSTS build

@mavasani
Copy link
Contributor Author

mavasani commented Oct 3, 2018

@jaredpar I have tried to requeue the build few times, but it still fails the Linux Mono test.

@jaredpar
Copy link
Member

jaredpar commented Oct 3, 2018

@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.

@mavasani
Copy link
Contributor Author

mavasani commented Oct 3, 2018

Thanks @jaredpar. @CyrusNajmabadi any more concerns/feedback? We can merge once Cyrus sign's off.

@jaredpar
Copy link
Member

jaredpar commented Oct 3, 2018

@mavasani this PR will fix this problem #30286

@CyrusNajmabadi
Copy link
Member

@mavasani Will do one more pass to make sure everything looks good :)


namespace Microsoft.CodeAnalysis.FindUsages
{
using ReferenceInfoMap = ImmutableDictionary<string, ImmutableArray<string>>;
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, makes sense.


In reply to: 222369807 [](ancestors = 222369807)

}

private static ReferenceInfoMap GetOrCreateReferenceInfo(ValueUsageInfo valueUsageInfo)
=> s_valueUsageInfoToReferenceInfoMap.GetOrAdd(valueUsageInfo, CreateReferenceInfo);
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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);
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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

Copy link
Contributor Author

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);
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure.


In reply to: 222372159 [](ancestors = 222372159)

// 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())
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Oct 3, 2018

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

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a 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.

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.

6 participants