Exemplo n.º 1
0
        public async Task <ExtractMethodResult> ExtractMethodAsync(
            Document document,
            TextSpan textSpan,
            bool localFunction,
            ExtractMethodGenerationOptions options,
            CancellationToken cancellationToken)
        {
            var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            var validator = CreateSelectionValidator(semanticDocument, textSpan, options.ExtractOptions, localFunction);

            var selectionResult = await validator.GetValidSelectionAsync(cancellationToken).ConfigureAwait(false);

            if (!selectionResult.ContainsValidContext)
            {
                return(new FailedExtractMethodResult(selectionResult.Status));
            }

            cancellationToken.ThrowIfCancellationRequested();

            // extract method
            var extractor = CreateMethodExtractor((TResult)selectionResult, options, localFunction);

            return(await extractor.ExtractMethodAsync(cancellationToken).ConfigureAwait(false));
        }
Exemplo n.º 2
0
 public MethodExtractor(
     SelectionResult selectionResult,
     ExtractMethodGenerationOptions options,
     bool localFunction)
 {
     Contract.ThrowIfNull(selectionResult);
     OriginalSelectionResult = selectionResult;
     Options       = options;
     LocalFunction = localFunction;
 }
Exemplo n.º 3
0
        protected static async Task <SyntaxNode> ExtractMethodAsync(
            TestWorkspace workspace,
            TestHostDocument testDocument,
            bool succeed = true,
            bool dontPutOutOrRefOnStruct = true,
            bool allowBestEffort         = false)
        {
            var document = workspace.CurrentSolution.GetDocument(testDocument.Id);

            Assert.NotNull(document);

            var options = new ExtractMethodGenerationOptions(
                ExtractOptions: new ExtractMethodOptions(dontPutOutOrRefOnStruct),
                CodeGenerationOptions: CodeGenerationOptions.GetDefault(document.Project.LanguageServices),
                AddImportOptions: AddImportPlacementOptions.Default,
                NamingPreferences: _ => NamingStylePreferences.Default);

            var semanticDocument = await SemanticDocument.CreateAsync(document, CancellationToken.None);

            var validator = new CSharpSelectionValidator(semanticDocument, testDocument.SelectedSpans.Single(), options.ExtractOptions, localFunction: false);

            var selectedCode = await validator.GetValidSelectionAsync(CancellationToken.None);

            if (!succeed && selectedCode.Status.FailedWithNoBestEffortSuggestion())
            {
                return(null);
            }

            Assert.True(selectedCode.ContainsValidContext);

            // extract method
            var extractor = new CSharpMethodExtractor((CSharpSelectionResult)selectedCode, options, localFunction: false);
            var result    = await extractor.ExtractMethodAsync(CancellationToken.None);

            Assert.NotNull(result);
            Assert.Equal(succeed,
                         result.Succeeded ||
                         result.SucceededWithSuggestion ||
                         (allowBestEffort && result.Status.HasBestEffort()));

            var(doc, _) = await result.GetFormattedDocumentAsync(CodeCleanupOptions.GetDefault(document.Project.LanguageServices), CancellationToken.None);

            return(doc == null
                ? null
                : await doc.GetSyntaxRootAsync());
        }
Exemplo n.º 4
0
        private static async Task <ImmutableArray <CodeAction> > GetCodeActionsAsync(
            Document document,
            TextSpan textSpan,
            ExtractMethodGenerationOptions extractOptions,
            CodeCleanupOptions cleanupOptions,
            CancellationToken cancellationToken)
        {
            using var _ = ArrayBuilder <CodeAction> .GetInstance(out var actions);

            var methodAction = await ExtractMethodAsync(document, textSpan, extractOptions, cleanupOptions, cancellationToken).ConfigureAwait(false);

            actions.AddIfNotNull(methodAction);

            var localFunctionAction = await ExtractLocalFunctionAsync(document, textSpan, extractOptions, cleanupOptions, cancellationToken).ConfigureAwait(false);

            actions.AddIfNotNull(localFunctionAction);

            return(actions.ToImmutable());
        }
    public static async ValueTask <ExtractMethodGenerationOptions> GetExtractMethodGenerationOptionsAsync(this Document document, ExtractMethodGenerationOptions?fallbackOptions, CancellationToken cancellationToken)
    {
        fallbackOptions ??= ExtractMethodGenerationOptions.GetDefault(document.Project.LanguageServices);

        var extractOptions = fallbackOptions.Value.ExtractOptions;
        var codeGenerationOptions = await document.GetCodeGenerationOptionsAsync(fallbackOptions.Value.CodeGenerationOptions, cancellationToken).ConfigureAwait(false);

        var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions.Value.AddImportOptions, cancellationToken).ConfigureAwait(false);

        var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

        var namingPreferences = documentOptions.GetOption(NamingStyleOptions.NamingPreferences, document.Project.Language);
        var namingPreferencesProvider = new NamingStylePreferencesProvider(language => namingPreferences);

        return(new ExtractMethodGenerationOptions(
                   extractOptions,
                   codeGenerationOptions,
                   addImportOptions,
                   namingPreferencesProvider));
    }
        private static async Task <ExtractMethodResult?> TryWithoutMakingValueTypesRefAsync(
            Document document, TextSpan span, ExtractMethodResult result, ExtractMethodGenerationOptions options, CancellationToken cancellationToken)
        {
            if (options.ExtractOptions.DontPutOutOrRefOnStruct || !result.Reasons.IsSingle())
            {
                return(null);
            }

            var reason = result.Reasons.FirstOrDefault();
            var length = FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.IndexOf(':');

            if (reason != null && length > 0 && reason.IndexOf(FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.Substring(0, length), 0, length, StringComparison.Ordinal) >= 0)
            {
                var newResult = await ExtractMethodService.ExtractMethodAsync(
                    document,
                    span,
                    localFunction : false,
                    options with {
                    ExtractOptions = options.ExtractOptions with {
                        DontPutOutOrRefOnStruct = true
                    }
                },
Exemplo n.º 7
0
        public void OptionsAreMessagePackSerializable(string language)
        {
            var messagePackOptions = MessagePackSerializerOptions.Standard.WithResolver(MessagePackFormatters.DefaultResolver);

            using var workspace = new AdhocWorkspace();
            var languageServices = workspace.Services.GetLanguageServices(language);

            var options = new object[]
            {
                SimplifierOptions.GetDefault(languageServices),
                SyntaxFormattingOptions.GetDefault(languageServices),
                CodeCleanupOptions.GetDefault(languageServices),
                CodeGenerationOptions.GetDefault(languageServices),
                IdeCodeStyleOptions.GetDefault(languageServices),
                CodeActionOptions.GetDefault(languageServices),
                IndentationOptions.GetDefault(languageServices),
                ExtractMethodGenerationOptions.GetDefault(languageServices),

                // some non-default values:
                new VisualBasicIdeCodeStyleOptions(
                    new IdeCodeStyleOptions.CommonOptions()
                {
                    AllowStatementImmediatelyAfterBlock = new CodeStyleOption2 <bool>(false, NotificationOption2.Error)
                },
                    PreferredModifierOrder: new CodeStyleOption2 <string>("Public Private", NotificationOption2.Error))
            };

            foreach (var original in options)
            {
                using var stream = new MemoryStream();
                MessagePackSerializer.Serialize(stream, original, messagePackOptions);
                stream.Position = 0;

                var deserialized = MessagePackSerializer.Deserialize(original.GetType(), stream, messagePackOptions);
                Assert.Equal(original, deserialized);
            }
        }
Exemplo n.º 8
0
 protected abstract TExtractor CreateMethodExtractor(TResult selectionResult, ExtractMethodGenerationOptions options, bool localFunction);
Exemplo n.º 9
0
        private static async Task <CodeAction> ExtractMethodAsync(Document document, TextSpan textSpan, ExtractMethodGenerationOptions extractOptions, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken)
        {
            var result = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : false,
                extractOptions,
                cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                return(null);
            }

            return(CodeAction.Create(
                       FeaturesResources.Extract_method,
                       async c =>
            {
                var(document, invocationNameToken) = await result.GetFormattedDocumentAsync(cleanupOptions, c).ConfigureAwait(false);
                return await AddRenameAnnotationAsync(document, invocationNameToken, c).ConfigureAwait(false);
            },
                       nameof(FeaturesResources.Extract_method)));
        }
Exemplo n.º 10
0
        private static async Task <CodeAction> ExtractLocalFunctionAsync(Document document, TextSpan textSpan, ExtractMethodGenerationOptions extractOptions, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (!syntaxFacts.SupportsLocalFunctionDeclaration(syntaxTree.Options))
            {
                return(null);
            }

            var localFunctionResult = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : true,
                extractOptions,
                cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(localFunctionResult);

            if (localFunctionResult.Succeeded || localFunctionResult.SucceededWithSuggestion)
            {
                var codeAction = CodeAction.Create(
                    FeaturesResources.Extract_local_function,
                    async c =>
                {
                    var(document, invocationNameToken) = await localFunctionResult.GetFormattedDocumentAsync(cleanupOptions, c).ConfigureAwait(false);
                    return(await AddRenameAnnotationAsync(document, invocationNameToken, c).ConfigureAwait(false));
                },
                    nameof(FeaturesResources.Extract_local_function));
                return(codeAction);
            }

            return(null);
        }
Exemplo n.º 11
0
 public CSharpMethodExtractor(CSharpSelectionResult result, ExtractMethodGenerationOptions options, bool localFunction)
     : base(result, options, localFunction)
 {
 }
Exemplo n.º 12
0
 public static Task <ExtractMethodResult> ExtractMethodAsync(Document document, TextSpan textSpan, bool localFunction, ExtractMethodGenerationOptions options, CancellationToken cancellationToken)
 => document.GetRequiredLanguageService <IExtractMethodService>().ExtractMethodAsync(document, textSpan, localFunction, options, cancellationToken);