Skip to content

Commit a27630b

Browse files
Pull computation up in extract method
1 parent bd782d4 commit a27630b

File tree

1 file changed

+57
-60
lines changed

1 file changed

+57
-60
lines changed

src/Features/Core/Portable/ExtractMethod/MethodExtractor.Analyzer.cs

Lines changed: 57 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -505,30 +505,30 @@ private static ImmutableArray<VariableInfo> GetMethodParameters(Dictionary<ISymb
505505
/// variable we don't understand has <see cref="VariableStyle.None"/></param>
506506
private void GenerateVariableInfoMap(
507507
bool bestEffort,
508-
SemanticModel model,
508+
SemanticModel semanticModel,
509509
DataFlowAnalysis dataFlowAnalysisData,
510510
Dictionary<ISymbol, List<SyntaxToken>> symbolMap,
511511
bool isInPrimaryConstructorBaseType,
512512
out Dictionary<ISymbol, VariableInfo> variableInfoMap,
513513
out List<ISymbol> failedVariables)
514514
{
515-
Contract.ThrowIfNull(model);
515+
Contract.ThrowIfNull(semanticModel);
516516
Contract.ThrowIfNull(dataFlowAnalysisData);
517517

518518
variableInfoMap = [];
519519
failedVariables = [];
520520

521521
// create map of each data
522-
var capturedMap = new HashSet<ISymbol>(dataFlowAnalysisData.Captured);
523-
var dataFlowInMap = new HashSet<ISymbol>(dataFlowAnalysisData.DataFlowsIn);
524-
var dataFlowOutMap = new HashSet<ISymbol>(dataFlowAnalysisData.DataFlowsOut);
525-
var alwaysAssignedMap = new HashSet<ISymbol>(dataFlowAnalysisData.AlwaysAssigned);
526-
var variableDeclaredMap = new HashSet<ISymbol>(dataFlowAnalysisData.VariablesDeclared);
527-
var readInsideMap = new HashSet<ISymbol>(dataFlowAnalysisData.ReadInside);
528-
var writtenInsideMap = new HashSet<ISymbol>(dataFlowAnalysisData.WrittenInside);
529-
var readOutsideMap = new HashSet<ISymbol>(dataFlowAnalysisData.ReadOutside);
530-
var writtenOutsideMap = new HashSet<ISymbol>(dataFlowAnalysisData.WrittenOutside);
531-
var unsafeAddressTakenMap = new HashSet<ISymbol>(dataFlowAnalysisData.UnsafeAddressTaken);
522+
using var _0 = GetPooledSymbolSet(dataFlowAnalysisData.Captured, out var capturedMap);
523+
using var _1 = GetPooledSymbolSet(dataFlowAnalysisData.DataFlowsIn, out var dataFlowInMap);
524+
using var _2 = GetPooledSymbolSet(dataFlowAnalysisData.DataFlowsOut, out var dataFlowOutMap);
525+
using var _3 = GetPooledSymbolSet(dataFlowAnalysisData.AlwaysAssigned, out var alwaysAssignedMap);
526+
using var _4 = GetPooledSymbolSet(dataFlowAnalysisData.VariablesDeclared, out var variableDeclaredMap);
527+
using var _5 = GetPooledSymbolSet(dataFlowAnalysisData.ReadInside, out var readInsideMap);
528+
using var _6 = GetPooledSymbolSet(dataFlowAnalysisData.WrittenInside, out var writtenInsideMap);
529+
using var _7 = GetPooledSymbolSet(dataFlowAnalysisData.ReadOutside, out var readOutsideMap);
530+
using var _8 = GetPooledSymbolSet(dataFlowAnalysisData.WrittenOutside, out var writtenOutsideMap);
531+
using var _9 = GetPooledSymbolSet(dataFlowAnalysisData.UnsafeAddressTaken, out var unsafeAddressTakenMap);
532532

533533
// gather all meaningful symbols for the span.
534534
var candidates = new HashSet<ISymbol>(readInsideMap);
@@ -538,6 +538,7 @@ private void GenerateVariableInfoMap(
538538
// Need to analyze from the start of what we're extracting to the end of the scope that this variable could
539539
// have been referenced in.
540540
var analysisRange = TextSpan.FromBounds(SelectionResult.FinalSpan.Start, SelectionResult.GetContainingScope().Span.End);
541+
var selectionOperation = semanticModel.GetOperation(SelectionResult.GetContainingScope());
541542

542543
foreach (var symbol in candidates)
543544
{
@@ -582,30 +583,22 @@ private void GenerateVariableInfoMap(
582583

583584
// variable that is declared inside but never referenced outside. just ignore it and move to next one.
584585
if (variableDeclared && !dataFlowOut && !readOutside && !writtenOutside)
585-
{
586586
continue;
587-
}
588587

589588
// parameter defined inside of the selection (such as lambda parameter) will be ignored (bug # 10964)
590589
if (symbol is IParameterSymbol && variableDeclared)
591-
{
592590
continue;
593-
}
594591

595-
var type = GetSymbolType(model, symbol, analysisRange);
592+
var type = GetSymbolType(symbol);
596593
if (type == null)
597-
{
598594
continue;
599-
}
600595

601596
// If the variable doesn't have a name, it is invalid.
602597
if (symbol.Name.IsEmpty())
603-
{
604598
continue;
605-
}
606599

607600
if (!TryGetVariableStyle(
608-
bestEffort, symbolMap, symbol, model, type,
601+
bestEffort, symbolMap, symbol, semanticModel, type,
609602
captured, dataFlowIn, dataFlowOut, alwaysAssigned, variableDeclared,
610603
readInside, writtenInside, readOutside, writtenOutside, unsafeAddressTaken,
611604
out var variableStyle))
@@ -620,6 +613,48 @@ private void GenerateVariableInfoMap(
620613
symbol,
621614
CreateFromSymbol(symbol, type, variableStyle, variableDeclared));
622615
}
616+
617+
return;
618+
619+
PooledDisposer<PooledHashSet<ISymbol>> GetPooledSymbolSet(ImmutableArray<ISymbol> symbols, out PooledHashSet<ISymbol> symbolSet)
620+
{
621+
var disposer = PooledHashSet<ISymbol>.GetInstance(out symbolSet);
622+
symbolSet.AddRange(symbols);
623+
return disposer;
624+
}
625+
626+
ITypeSymbol? GetSymbolType(ISymbol symbol)
627+
{
628+
var type = symbol switch
629+
{
630+
ILocalSymbol local => local.Type,
631+
IParameterSymbol parameter => parameter.Type,
632+
IRangeVariableSymbol rangeVariable => GetRangeVariableType(semanticModel, rangeVariable),
633+
_ => throw ExceptionUtilities.UnexpectedValue(symbol)
634+
};
635+
636+
if (type is null)
637+
return type;
638+
639+
// Check if null is possibly assigned to the symbol. If it is, leave nullable annotation as is, otherwise we
640+
// can modify the annotation to be NotAnnotated to code that more likely matches the user's intent.
641+
642+
if (type.NullableAnnotation is not NullableAnnotation.Annotated)
643+
return type;
644+
645+
// For Extract-Method we don't care about analyzing the declaration of this variable. For example, even if
646+
// it was initially assigned 'null' for the purposes of determining the type of it for a return value, all
647+
// we care is if it is null at the end of the selection. If it is only assigned non-null values, for
648+
// example, we want to treat it as non-null.
649+
if (selectionOperation is not null &&
650+
NullableHelpers.IsSymbolAssignedPossiblyNullValue(
651+
this.SemanticFacts, semanticModel, selectionOperation, symbol, analysisRange, includeDeclaration: false, this.CancellationToken) == false)
652+
{
653+
return type.WithNullableAnnotation(NullableAnnotation.NotAnnotated);
654+
}
655+
656+
return type;
657+
}
623658
}
624659

625660
private static void AddVariableToMap(IDictionary<ISymbol, VariableInfo> variableInfoMap, ISymbol localOrParameter, VariableInfo variableInfo)
@@ -711,44 +746,6 @@ private bool SelectionContainsOnlyIdentifierWithSameType(ITypeSymbol type)
711746
return type.Equals(SelectionResult.GetContainingScopeType());
712747
}
713748

714-
private ITypeSymbol? GetSymbolType(
715-
SemanticModel semanticModel,
716-
ISymbol symbol,
717-
TextSpan analysisRange)
718-
{
719-
var type = symbol switch
720-
{
721-
ILocalSymbol local => local.Type,
722-
IParameterSymbol parameter => parameter.Type,
723-
IRangeVariableSymbol rangeVariable => GetRangeVariableType(semanticModel, rangeVariable),
724-
_ => throw ExceptionUtilities.UnexpectedValue(symbol)
725-
};
726-
727-
if (type is null)
728-
return type;
729-
730-
// Check if null is possibly assigned to the symbol. If it is, leave nullable annotation as is, otherwise we
731-
// can modify the annotation to be NotAnnotated to code that more likely matches the user's intent.
732-
733-
if (type.NullableAnnotation is not NullableAnnotation.Annotated)
734-
return type;
735-
736-
var selectionOperation = semanticModel.GetOperation(SelectionResult.GetContainingScope());
737-
738-
// For Extract-Method we don't care about analyzing the declaration of this variable. For example, even if
739-
// it was initially assigned 'null' for the purposes of determining the type of it for a return value, all
740-
// we care is if it is null at the end of the selection. If it is only assigned non-null values, for
741-
// example, we want to treat it as non-null.
742-
if (selectionOperation is not null &&
743-
NullableHelpers.IsSymbolAssignedPossiblyNullValue(
744-
this.SemanticFacts, semanticModel, selectionOperation, symbol, analysisRange, includeDeclaration: false, this.CancellationToken) == false)
745-
{
746-
return type.WithNullableAnnotation(NullableAnnotation.NotAnnotated);
747-
}
748-
749-
return type;
750-
}
751-
752749
protected static VariableStyle AlwaysReturn(VariableStyle style)
753750
{
754751
if (style == VariableStyle.InputOnly)

0 commit comments

Comments
 (0)