public CSharpMethodExtractor(CSharpSelectionResult result) : base(result) { }
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)); }