Ejemplo n.º 1
0
 public CSharpMethodExtractor(CSharpSelectionResult result) :
     base(result)
 {
 }
Ejemplo n.º 2
0
        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));
        }