-
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
Continued Extract method cleanup #76577
Continued Extract method cleanup #76577
Conversation
@@ -1520,7 +1520,7 @@ public async Task AnonymousTypeMember1() | |||
{ | |||
var code = """ | |||
using System; | |||
class C { void M() { {|r:var x = new { {|b:String|} = true }; |}} } | |||
class C { void M() { {|r:var x = new { {|b:String|} = true };|} } } |
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: the test previously were non-functional. they were not actually validating that the spans unless a special bit was set on a reseult avlue (which wasn't computed properly). I also remove this bit in a follow up pr because the whole "feature adds special out of band data, for tests to validate, but which doesn't impactthe feature itself" is an awful paradigm.
@@ -16,16 +16,13 @@ namespace Microsoft.CodeAnalysis.CSharp.ExtractMethod; | |||
[method: ImportingConstructor] | |||
[method: SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] | |||
internal sealed partial class CSharpExtractMethodService() : AbstractExtractMethodService< | |||
CSharpExtractMethodService.CSharpSelectionValidator, | |||
CSharpExtractMethodService.CSharpMethodExtractor, | |||
CSharpExtractMethodService.CSharpSelectionResult, |
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.
got rid of theese generics. they are not needed, and just add type system complexity.
{ | ||
var analyzer = new CSharpAnalyzer(selectionResult, localFunction, cancellationToken); | ||
return analyzer.Analyze(); | ||
} |
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.
inlined these static construction methods at callsite.
@@ -202,9 +190,25 @@ protected override SyntaxNode GetCallSiteContainerFromOutermostMoveInVariable(Ca | |||
return declStatement.Parent; | |||
} | |||
|
|||
private bool ShouldPutUnsafeModifier() |
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 used to be on the strongly typed CSharpXXX types, but were only ever called from a single location (here). so instead of needing all the generic type system wonkyness to pass in one of these subtypes, just to call special methods (not on the base type), i just moved the mtehods to the places that use them. simple, easy.
var root = selectionResult.SemanticDocument.Root; | ||
var result = preservationService.SaveTriviaAroundSelection(root, selectionResult.FinalSpan); | ||
return new CSharpTriviaResult( | ||
await selectionResult.SemanticDocument.WithSyntaxRootAsync(result.Root, cancellationToken).ConfigureAwait(false), |
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.
static factories inlined to callsite.
} | ||
|
||
private CSharpTriviaResult(SemanticDocument document, ITriviaSavedResult result) | ||
: base(document, result, (int)SyntaxKind.EndOfLineTrivia, (int)SyntaxKind.WhitespaceTrivia) |
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.
primary constructorified.
|
||
protected override SyntaxNode GetInsertionPointNode( | ||
AnalyzerResult analyzerResult, CancellationToken cancellationToken) | ||
{ | ||
var originalSpanStart = OriginalSelectionResult.OriginalSpan.Start; | ||
var originalSpanStart = OriginalSelectionResult.FinalSpan.Start; |
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.
unified a lot of the behavior around which pieces of data we use. the user's original selection, or what we updated the selection to.
Note: the followup PR on this cleans this up much further, but separating out this data into two types so that the feature itself is very clear about if it's using the pre/post selection and why.
@@ -24,10 +24,9 @@ internal abstract partial class CSharpSelectionResult | |||
private sealed class ExpressionResult( | |||
SemanticDocument document, | |||
SelectionType selectionType, | |||
TextSpan originalSpan, |
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.
remove this. this should only be the starting info from the user. we don't want to pass this along as it's actively confusing as to when you'd use this over 'final span'.
public override bool ContainsNonReturnExitPointsStatements(ImmutableArray<SyntaxNode> jumpsOutOfRegion) | ||
=> jumpsOutOfRegion.Any(n => n is not ReturnStatementSyntax); | ||
|
||
public override ImmutableArray<StatementSyntax> GetOuterReturnStatements(SyntaxNode commonRoot, ImmutableArray<SyntaxNode> jumpsOutOfRegion) |
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 a move.
} | ||
|
||
return false; | ||
} |
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.
moved to common location. uses IBLockFacts to unify logic for C#/vb.
selectionInfo = AdjustFinalTokensBasedOnContext(selectionInfo, model, cancellationToken); | ||
selectionInfo = AssignFinalSpan(selectionInfo, text); | ||
selectionInfo = ApplySpecialCases(selectionInfo, text, SemanticDocument.SyntaxTree.Options, _localFunction); |
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 used to passa a lot of instance-state data to helper instance methods. i cleaned that up to access off of 'this' instead.
|
||
var (firstStatement, lastStatement) = this.SelectionResult.GetFlowAnalysisNodeRange(); | ||
return this.SemanticModel.AnalyzeDataFlow(firstStatement, lastStatement); | ||
} |
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.
a high level goal was to stop exposing the 'start/end nodes' and having callers then do things like AnalyzeDataFlow/AnalyzeControlFlow. By the end of hte cleanup, the nodes are not exposed, and that data is computed once and cached for all callers to use.
@@ -226,5 +265,49 @@ protected static SyntaxNode AddAnnotations(SyntaxNode root, IEnumerable<(SyntaxN | |||
var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); | |||
return root.ReplaceNodes(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); | |||
} | |||
|
|||
public OperationStatus ValidateSelectionResult(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.
trying to move common logic when i can between c# and vb to a common location.
return OperationStatus.SucceededStatus; | ||
} | ||
|
||
protected bool IsFinalSpanSemanticallyValidSpan(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.
this is a move.
if (selectionInfo.Status.Failed) | ||
return (null, selectionInfo.Status); | ||
|
||
TStatementSyntax? firstStatement = 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.
this will get more cleaned up in followup. but the idea here is again just pulling logic up from C#/VB to common location.
@@ -158,12 +149,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod | |||
Return declStatement.Parent | |||
End Function | |||
|
|||
Private Function IsUnderModuleBlock() As Boolean |
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.
vb specific helpers that were on VBSelectionResult, like with C#, these were called in one lcation. so i just moved the helpers right to that location.
@JoeRobich @ToddGrun ptal. thanks :) |
Co-authored-by: Joey Robichaud <joseph.robichaud@microsoft.com>
@@ -316,18 +313,19 @@ protected ImmutableArray<TStatementSyntax> AppendReturnStatementIfNeeded(Immutab | |||
protected static HashSet<SyntaxAnnotation> CreateVariableDeclarationToRemoveMap( | |||
IEnumerable<VariableInfo> variables, CancellationToken cancellationToken) | |||
{ | |||
var annotations = new List<(SyntaxToken, SyntaxAnnotation)>(); | |||
var annotations = new MultiDictionary<SyntaxToken, SyntaxAnnotation>(); |
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.
Oh, I see, MethodExtractor.GetAnnotatedDocumentAndInsertionPointAsync is simplified by changing AddIdentifierTokenAnnotationPair to use a MultiDictionary
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 just more accurately reflects what the code was doing. It was building a list of K/V pairs, then later flattening to an IGrouping (or ILookup) of K to many Vs.
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.
Followup to #76550