protected override ImmutableArray <StatementSyntax> GetInitialStatementsForMethodDefinitions() { Contract.ThrowIfFalse(IsExtractMethodOnExpression(CSharpSelectionResult)); // special case for array initializer var returnType = AnalyzerResult.ReturnType; var containingScope = CSharpSelectionResult.GetContainingScope(); ExpressionSyntax expression; if ( returnType.TypeKind == TypeKind.Array && containingScope is InitializerExpressionSyntax ) { var typeSyntax = returnType.GenerateTypeSyntax(); expression = SyntaxFactory.ArrayCreationExpression( typeSyntax as ArrayTypeSyntax, containingScope as InitializerExpressionSyntax ); } else { expression = containingScope as ExpressionSyntax; } if (AnalyzerResult.HasReturnType) { return(ImmutableArray.Create <StatementSyntax>( SyntaxFactory.ReturnStatement( WrapInCheckedExpressionIfNeeded(expression) ) )); } else { return(ImmutableArray.Create <StatementSyntax>( SyntaxFactory.ExpressionStatement( WrapInCheckedExpressionIfNeeded(expression) ) )); } }
protected override SyntaxNode GetOutermostCallSiteContainerToProcess( CancellationToken cancellationToken ) { var callSiteContainer = GetCallSiteContainerFromOutermostMoveInVariable( cancellationToken ); if (callSiteContainer != null) { return(callSiteContainer); } else { var firstStatement = CSharpSelectionResult.GetFirstStatementUnderContainer(); return(firstStatement.Parent); } }
protected override ImmutableArray <StatementSyntax> GetInitialStatementsForMethodDefinitions() { var firstSeen = false; var firstStatementUnderContainer = CSharpSelectionResult.GetFirstStatementUnderContainer(); var lastStatementUnderContainer = CSharpSelectionResult.GetLastStatementUnderContainer(); using var _ = ArrayBuilder <StatementSyntax> .GetInstance(out var list); foreach ( var statement in GetStatementsFromContainer( firstStatementUnderContainer.Parent ) ) { // reset first seen if (!firstSeen) { firstSeen = statement == firstStatementUnderContainer; } // continue until we see the first statement if (!firstSeen) { continue; } list.Add(statement); // exit if we see last statement if (statement == lastStatementUnderContainer) { break; } } return(list.ToImmutable()); }
protected override SyntaxNode GetFirstStatementOrInitializerSelectedAtCallSite() { var scope = (SyntaxNode)CSharpSelectionResult.GetContainingScopeOf <StatementSyntax>(); if (scope == null) { scope = CSharpSelectionResult.GetContainingScopeOf <FieldDeclarationSyntax>(); } if (scope == null) { scope = CSharpSelectionResult.GetContainingScopeOf <ConstructorInitializerSyntax>(); } if (scope == null) { // This is similar to FieldDeclaration case but we only want to do this // if the member has an expression body. scope = CSharpSelectionResult.GetContainingScopeOf <ArrowExpressionClauseSyntax>().Parent; } return(scope); }
public CSharpMethodExtractor(CSharpSelectionResult result) : base(result) { }
public CSharpMethodExtractor(CSharpSelectionResult result, bool localFunction) : base(result, localFunction) { }
public override async Task <SelectionResult> GetValidSelectionAsync( CancellationToken cancellationToken ) { if (!ContainsValidSelection) { return(NullSelection); } var text = SemanticDocument.Text; var root = SemanticDocument.Root; var model = SemanticDocument.SemanticModel; var doc = SemanticDocument; // go through pipe line and calculate information about the user selection var selectionInfo = GetInitialSelectionInfo(root, text); selectionInfo = AssignInitialFinalTokens(selectionInfo, root, cancellationToken); selectionInfo = AdjustFinalTokensBasedOnContext( selectionInfo, model, cancellationToken ); selectionInfo = AssignFinalSpan(selectionInfo, text); selectionInfo = ApplySpecialCases(selectionInfo, text); selectionInfo = CheckErrorCasesAndAppendDescriptions(selectionInfo, root); // there was a fatal error that we couldn't even do negative preview, return error result if (selectionInfo.Status.FailedWithNoBestEffortSuggestion()) { return(new ErrorSelectionResult(selectionInfo.Status)); } var controlFlowSpan = GetControlFlowSpan(selectionInfo); if (!selectionInfo.SelectionInExpression) { var statementRange = GetStatementRangeContainedInSpan <StatementSyntax>( root, controlFlowSpan, cancellationToken ); if (statementRange == null) { selectionInfo = selectionInfo.WithStatus( s => s.With( OperationStatusFlag.None, CSharpFeaturesResources.Can_t_determine_valid_range_of_statements_to_extract ) ); return(new ErrorSelectionResult(selectionInfo.Status)); } var isFinalSpanSemanticallyValid = IsFinalSpanSemanticallyValidSpan( model, controlFlowSpan, statementRange, cancellationToken ); if (!isFinalSpanSemanticallyValid) { // check control flow only if we are extracting statement level, not expression // level. you can not have goto that moves control out of scope in expression level // (even in lambda) selectionInfo = selectionInfo.WithStatus( s => s.With( OperationStatusFlag.BestEffort, CSharpFeaturesResources.Not_all_code_paths_return ) ); } } return(await CSharpSelectionResult .CreateAsync( selectionInfo.Status, selectionInfo.OriginalSpan, selectionInfo.FinalSpan, Options, selectionInfo.SelectionInExpression, doc, selectionInfo.FirstTokenInFinalSpan, selectionInfo.LastTokenInFinalSpan, cancellationToken ) .ConfigureAwait(false)); }
protected override SyntaxNode GetLastStatementOrInitializerSelectedAtCallSite() { return(CSharpSelectionResult.GetLastStatementUnderContainer()); }
protected override SyntaxNode GetFirstStatementOrInitializerSelectedAtCallSite() => CSharpSelectionResult.GetFirstStatementUnderContainer();
protected override SyntaxNode GetLastStatementOrInitializerSelectedAtCallSite() { // it is a single statement case. either first statement is same as last statement or // last statement belongs (embedded statement) to the first statement. return(CSharpSelectionResult.GetFirstStatement()); }
protected override ImmutableArray <StatementSyntax> GetInitialStatementsForMethodDefinitions() { Contract.ThrowIfFalse(IsExtractMethodOnSingleStatement(CSharpSelectionResult)); return(ImmutableArray.Create(CSharpSelectionResult.GetFirstStatement())); }
public CSharpMethodExtractor(CSharpSelectionResult result, ExtractMethodGenerationOptions options, bool localFunction) : base(result, options, localFunction) { }
public override async Task <SelectionResult> GetValidSelectionAsync(CancellationToken cancellationToken) { if (!this.ContainsValidSelection) { return(NullSelection); } var text = this.SemanticDocument.Text; var root = this.SemanticDocument.Root; var model = this.SemanticDocument.SemanticModel; var doc = this.SemanticDocument; // go through pipe line and calculate information about the user selection var selectionInfo = GetInitialSelectionInfo(root, text, cancellationToken); selectionInfo = AssignInitialFinalTokens(selectionInfo, root, cancellationToken); selectionInfo = AdjustFinalTokensBasedOnContext(selectionInfo, model, cancellationToken); selectionInfo = AssignFinalSpan(selectionInfo, text, cancellationToken); selectionInfo = ApplySpecialCases(selectionInfo, text, cancellationToken); selectionInfo = CheckErrorCasesAndAppendDescriptions(selectionInfo, root, model, cancellationToken); // there was a fatal error that we couldn't even do negative preview, return error result if (selectionInfo.Status.FailedWithNoBestEffortSuggestion()) { return(new ErrorSelectionResult(selectionInfo.Status)); } var controlFlowSpan = GetControlFlowSpan(selectionInfo); if (!selectionInfo.SelectionInExpression) { var statementRange = GetStatementRangeContainedInSpan <StatementSyntax>(root, controlFlowSpan, cancellationToken); if (statementRange == null) { selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.Can_t_determine_valid_range_of_statements_to_extract)); return(new ErrorSelectionResult(selectionInfo.Status)); } var isFinalSpanSemanticallyValid = IsFinalSpanSemanticallyValidSpan(model, controlFlowSpan, statementRange, cancellationToken); if (!isFinalSpanSemanticallyValid) { // check control flow only if we are extracting statement level, not expression // level. you can not have goto that moves control out of scope in expression level // (even in lambda) selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.Not_all_code_paths_return)); } } // Warn if local functions are in selection since data flow analysis // cannot correctly analyze them // https://github.com/dotnet/roslyn/issues/14214 if (SpanInvolvesLocalFunction(selectionInfo.FinalSpan, model, root)) { selectionInfo = selectionInfo.WithStatus(s => s.With( OperationStatusFlag.Succeeded | OperationStatusFlag.BestEffort, CSharpFeaturesResources.Warning_Extracting_a_local_function_reference_may_produce_invalid_code)); var commonRoot = selectionInfo.CommonRootFromOriginalSpan; var annotated = commonRoot.WithAdditionalAnnotations( WarningAnnotation.Create(CSharpFeaturesResources.Warning_Extracting_a_local_function_reference_may_produce_invalid_code)); doc = await doc.WithSyntaxRootAsync( root.ReplaceNode(commonRoot, annotated), cancellationToken).ConfigureAwait(false); selectionInfo.FirstTokenInOriginalSpan = doc.Root.FindToken(selectionInfo.FirstTokenInOriginalSpan.SpanStart); selectionInfo.LastTokenInOriginalSpan = doc.Root.FindToken(selectionInfo.LastTokenInOriginalSpan.SpanStart); selectionInfo.FirstTokenInFinalSpan = doc.Root.FindToken(selectionInfo.FirstTokenInFinalSpan.SpanStart); selectionInfo.LastTokenInFinalSpan = doc.Root.FindToken(selectionInfo.LastTokenInFinalSpan.SpanStart); } return(await CSharpSelectionResult.CreateAsync( selectionInfo.Status, selectionInfo.OriginalSpan, selectionInfo.FinalSpan, this.Options, selectionInfo.SelectionInExpression, doc, selectionInfo.FirstTokenInFinalSpan, selectionInfo.LastTokenInFinalSpan, cancellationToken).ConfigureAwait(false)); }
protected override IEnumerable <StatementSyntax> GetInitialStatementsForMethodDefinitions() { Contract.ThrowIfFalse(IsExtractMethodOnSingleStatement(CSharpSelectionResult)); return(SpecializedCollections.SingletonEnumerable <StatementSyntax>(CSharpSelectionResult.GetFirstStatement())); }
protected override SyntaxNode GetFirstStatementOrInitializerSelectedAtCallSite() { return(CSharpSelectionResult.GetFirstStatement()); }