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

Continued Extract method cleanup (part 2) #76585

Merged
merged 11 commits into from
Jan 2, 2025

Conversation

CyrusNajmabadi
Copy link
Member

Followup to #76577.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 30, 2024
@@ -45,7 +46,7 @@ public override SyntaxNode GetContainingScope()
return CSharpSyntaxFacts.Instance.GetRootStandaloneExpression(scope);
}

public override (ITypeSymbol? returnType, bool returnsByRef) GetReturnType()
public override (ITypeSymbol? returnType, bool returnsByRef) GetReturnTypeInfo(CancellationToken cancellationToken)
Copy link
Member Author

Choose a reason for hiding this comment

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

renamed for clarity.

@@ -32,7 +32,7 @@ internal abstract partial class CSharpSelectionResult(
{
public static async Task<CSharpSelectionResult> CreateAsync(
SemanticDocument document,
SelectionInfo selectionInfo,
FinalSelectionInfo selectionInfo,
Copy link
Member Author

Choose a reason for hiding this comment

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

broke this into two type InitialSelectionInfo and FinalSelectionInfo so that we can make the variables clearer and so that later parts of EM don't use data they shouldn't.

@@ -210,37 +210,23 @@ public override ImmutableArray<StatementSyntax> GetOuterReturnStatements(SyntaxN
}

public override bool IsFinalSpanSemanticallyValidSpan(
TextSpan textSpan, ImmutableArray<StatementSyntax> returnStatements, CancellationToken cancellationToken)
Copy link
Member Author

Choose a reason for hiding this comment

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

very odd use of passing spans of selections around, when we have the actual data we need in nodes that we can use directly.

@@ -25,29 +24,73 @@ internal sealed partial class CSharpSelectionValidator(
{
private readonly bool _localFunction = localFunction;

protected override SelectionInfo UpdateSelectionInfo(
SelectionInfo selectionInfo, StatementSyntax? firstStatement, StatementSyntax? lastStatement, CancellationToken cancellationToken)
protected override InitialSelectionInfo GetInitialSelectionInfo(CancellationToken cancellationToken)
Copy link
Member Author

Choose a reason for hiding this comment

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

moved up from teh bottom, but adjusted heavily for simplicity.

Status = new OperationStatus(succeeded: false, FeaturesResources.Selection_does_not_contain_a_valid_token),
FirstTokenInOriginalSpan = firstTokenInSelection,
LastTokenInOriginalSpan = lastTokenInSelection
};
Copy link
Member Author

Choose a reason for hiding this comment

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

instead of having the moved code have this pattern (where it repeats the failure case multiple times), instead it just computes the failure code, and then if that happens, it creates the infla failure object once.

}

return isInExpressionOrHasReturnStatement;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

worlds most convoluted || expression.

@@ -670,7 +663,7 @@ private bool SelectionContainsOnlyIdentifierWithSameType(ITypeSymbol type)
return false;
}

return type.Equals(SelectionResult.GetContainingScopeType());
return type.Equals(SelectionResult.GetReturnType(this.CancellationToken));
Copy link
Member Author

Choose a reason for hiding this comment

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

GetContainingScopeType was a terribly confusing name. it's now just called GetReturnType, which defers to GetReturnTypeInfo


public SyntaxToken FirstTokenInFinalSpan { get; init; }
public SyntaxToken LastTokenInFinalSpan { get; init; }

public bool SelectionInExpression { get; init; }
public bool SelectionInSingleStatement { get; init; }
Copy link
Member Author

Choose a reason for hiding this comment

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

this doesn't need to be passed in. it can be determiend dynamically within this type. this also fixed an issue where the caller computed this in a different fashion from how this type computed it (a common issue in tnhe extract method codebase).

@@ -67,7 +103,7 @@ public SelectionType GetSelectionType()

var firstStatement = this.FirstTokenInFinalSpan.GetRequiredAncestor<TExecutableStatementSyntax>();
var lastStatement = this.LastTokenInFinalSpan.GetRequiredAncestor<TExecutableStatementSyntax>();
if (firstStatement == lastStatement || firstStatement.Span.Contains(lastStatement.Span))
if (firstStatement.Span.Contains(lastStatement.Span))
Copy link
Member Author

Choose a reason for hiding this comment

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

the latter check subsumes the former one.

@@ -105,15 +90,58 @@ private static bool IsValidStatementRange(
return firstStatement != null && lastStatement != null;
}

protected FinalSelectionInfo AssignFinalSpan(
InitialSelectionInfo initialSelectionInfo, FinalSelectionInfo finalSelectionInfo)
{
Copy link
Member Author

Choose a reason for hiding this comment

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

pulled up from C# and VB.

bool selectionInExpression,
SyntaxToken firstTokenInOriginalSpan,
SyntaxToken lastTokenInOriginalSpan,
CancellationToken cancellationToken)
Copy link
Member Author

Choose a reason for hiding this comment

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

pulled up from C# and VB.

@@ -347,14 +349,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
End If

' check whether selection reaches the end of the container
Dim lastToken = Me.SemanticDocument.Root.FindToken(textSpan.End)
If lastToken.Kind = SyntaxKind.None Then
Copy link
Member Author

Choose a reason for hiding this comment

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

things that can't happen due to tree invariants.

@@ -18,36 +18,86 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
MyBase.New(document, textSpan)
End Sub

Protected Overrides Function UpdateSelectionInfo(selectionInfo As SelectionInfo, firstStatement As StatementSyntax, lastStatement As StatementSyntax, cancellationToken As CancellationToken) As SelectionInfo
Protected Overrides Function GetInitialSelectionInfo(cancellationToken As CancellationToken) As InitialSelectionInfo
Dim root = Me.SemanticDocument.Root
Copy link
Member Author

Choose a reason for hiding this comment

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

simiklar to c#, this moved up from teh bottom.

@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review January 2, 2025 21:04
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner January 2, 2025 21:04
@CyrusNajmabadi
Copy link
Member Author

@JoeRobich @ToddGrun ptal. thanks! just one more cleanup pass after htis one.

@@ -70,27 +66,22 @@ public override (ITypeSymbol returnType, bool returnsByRef) GetReturnType()
switch (node)
{
case AccessorDeclarationSyntax access:
// property or event case
if (access.Parent == null || access.Parent.Parent == null)
Copy link
Member Author

Choose a reason for hiding this comment

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

remove code that can't happen.


var lastToken = this.SemanticDocument.Root.FindToken(textSpan.End);
Copy link
Member Author

Choose a reason for hiding this comment

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

very strange code that would recompute info already computed in earlier stages.


var lastToken = this.SemanticDocument.Root.FindToken(textSpan.End);
if (lastToken.Kind() == SyntaxKind.None)
Copy link
Member Author

Choose a reason for hiding this comment

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

not possible with syntax invariants.


var statusReason = CheckSpan();
if (statusReason is not null)
return InitialSelectionInfo.Failure(statusReason);
Copy link
Member Author

Choose a reason for hiding this comment

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

simpler approach of just computing failure reason, then returning failure object in that one case, instead of instantiating failure object (verbosely) over and over again.

return InitialSelectionInfo.Failure(statusReason);

return CreateInitialSelectionInfo(
selectionInExpression, firstTokenInSelection, lastTokenInSelection, cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

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

call to shared code for VB and C#.

}

protected override FinalSelectionInfo UpdateSelectionInfo(
InitialSelectionInfo initialSelectionInfo,
Copy link
Member Author

Choose a reason for hiding this comment

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

initialselection is now passed in data. FinalSelection is what is passed out. the domains are kept separated.

selectionInfo = AdjustFinalTokensBasedOnContext(selectionInfo, model, cancellationToken);
selectionInfo = AssignFinalSpan(selectionInfo);
selectionInfo = ApplySpecialCases(selectionInfo, SemanticDocument.SyntaxTree.Options, _localFunction);
selectionInfo = AssignFinalSpan(initialSelectionInfo, selectionInfo);
Copy link
Contributor

Choose a reason for hiding this comment

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

initialSelectionInfo

Seems odd that this and the next line pass in initialSelectionInfo

Copy link
Contributor

Choose a reason for hiding this comment

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

never mind, selectionInfo is also passed in

Copy link
Member Author

Choose a reason for hiding this comment

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

they're doing some work comparing the initial to the final they've computed so far. (yes, odd).

Copy link
Contributor

@ToddGrun ToddGrun left a comment

Choose a reason for hiding this comment

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

:shipit:

@CyrusNajmabadi CyrusNajmabadi merged commit 6b25538 into dotnet:main Jan 2, 2025
25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Jan 2, 2025
@CyrusNajmabadi CyrusNajmabadi deleted the extractMethodCleanup4 branch January 2, 2025 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead VSCode
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants