Skip to content

ExtractMethodCodeRefactoringProvider does not work with top-level statements #44260

@AlekseyTs

Description

@AlekseyTs

Add the following top level statement:

System.Console.WriteLine("string");

Select the string literal using mouse, observe ExtractMethodCodeRefactoringProvider to crash:

System.NullReferenceException : Object reference not set to an instance of an object.
 	Microsoft.CodeAnalysis.CSharp.Workspaces.dll!Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpCodeGenerationService.AddStatementsWorker<Microsoft.CodeAnalysis.SyntaxNode>(Microsoft.CodeAnalysis.SyntaxNode destinationMember, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.SyntaxNode> statements, Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationOptions options, System.Threading.CancellationToken cancellationToken) Line 498	C#
 	Microsoft.CodeAnalysis.CSharp.Workspaces.dll!Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpCodeGenerationService.AddStatements<Microsoft.CodeAnalysis.SyntaxNode>(Microsoft.CodeAnalysis.SyntaxNode destinationMember, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.SyntaxNode> statements, Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationOptions options, System.Threading.CancellationToken cancellationToken) Line 488	C#
>	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.ExtractMethod.MethodExtractor.CodeGenerator<Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax, Microsoft.CodeAnalysis.SyntaxNode>.GenerateAsync(System.Threading.CancellationToken cancellationToken) Line 100	C#
 	Microsoft.CodeAnalysis.CSharp.Features.dll!Microsoft.CodeAnalysis.CSharp.ExtractMethod.CSharpMethodExtractor.CSharpCodeGenerator.GenerateAsync(Microsoft.CodeAnalysis.ExtractMethod.InsertionPoint insertionPoint, Microsoft.CodeAnalysis.ExtractMethod.SelectionResult selectionResult, Microsoft.CodeAnalysis.ExtractMethod.MethodExtractor.AnalyzerResult analyzerResult, Microsoft.CodeAnalysis.Options.OptionSet options, bool localFunction, System.Threading.CancellationToken cancellationToken) Line 48	C#
 	Microsoft.CodeAnalysis.CSharp.Features.dll!Microsoft.CodeAnalysis.CSharp.ExtractMethod.CSharpMethodExtractor.GenerateCodeAsync(Microsoft.CodeAnalysis.ExtractMethod.InsertionPoint insertionPoint, Microsoft.CodeAnalysis.ExtractMethod.SelectionResult selectionResult, Microsoft.CodeAnalysis.ExtractMethod.MethodExtractor.AnalyzerResult analyzeResult, Microsoft.CodeAnalysis.Options.OptionSet options, System.Threading.CancellationToken cancellationToken) Line 94	C#
 	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.ExtractMethod.MethodExtractor.ExtractMethodAsync(System.Threading.CancellationToken cancellationToken) Line 65	C#
 	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.ExtractMethod.AbstractExtractMethodService<Microsoft.CodeAnalysis.CSharp.ExtractMethod.CSharpSelectionValidator, Microsoft.CodeAnalysis.CSharp.ExtractMethod.CSharpMethodExtractor, Microsoft.CodeAnalysis.CSharp.ExtractMethod.CSharpSelectionResult>.ExtractMethodAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Text.TextSpan textSpan, bool localFunction, Microsoft.CodeAnalysis.Options.OptionSet options, System.Threading.CancellationToken cancellationToken) Line 44	C#
 	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.ExtractMethod.ExtractMethodService.ExtractMethodAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Text.TextSpan textSpan, bool localFunction, Microsoft.CodeAnalysis.Options.OptionSet options, System.Threading.CancellationToken cancellationToken) Line 16	C#
 	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.CodeRefactorings.ExtractMethod.ExtractMethodCodeRefactoringProvider.ExtractLocalFunctionAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Text.TextSpan textSpan, System.Threading.CancellationToken cancellationToken) Line 102	C#
 	Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.CodeRefactorings.ExtractMethod.ExtractMethodCodeRefactoringProvider.GetCodeActionsAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Text.TextSpan textSpan, System.Threading.CancellationToken cancellationToken) Line 70	C#

The following line throws because options is null;

        private TDeclarationNode AddStatementsWorker<TDeclarationNode>(
            TDeclarationNode destinationMember,
            IEnumerable<SyntaxNode> statements,
            CodeGenerationOptions options,
            CancellationToken cancellationToken) where TDeclarationNode : SyntaxNode
        {
            var location = options.BestLocation;

However the method is indirectly called by Microsoft.CodeAnalysis.Features.dll!Microsoft.CodeAnalysis.ExtractMethod.MethodExtractor.CodeGenerator<Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax, Microsoft.CodeAnalysis.SyntaxNode>.GenerateAsync through an interface where options is an optional parameter with default value null and the argument is not provided explicitly.

Relates to #43563 (test plan for "top-level statements")

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions