Skip to content

Fix OOP crash issue with copilot change analysis #78931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PooledObjects;
Expand Down Expand Up @@ -265,7 +266,10 @@ private async Task<CopilotCodeFixAnalysis> ComputeCodeFixAnalysisAsync(
var firstAction = GetFirstAction(codeFixCollection.Fixes[0]);

var applicationTimeStopWatch = SharedStopwatch.StartNew();
var result = await firstAction.GetPreviewOperationsAsync(solution, cancellationToken).ConfigureAwait(false);
await firstAction
.GetPreviewOperationsAsync(solution, cancellationToken)
.ReportNonFatalErrorUnlessCancelledAsync(cancellationToken)
.ConfigureAwait(false);
callback((codeFixCollection, applicationTimeStopWatch.Elapsed));
},
consumeItems: static async (values, args, cancellationToken) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,75 +19,78 @@ internal static class CodeGenerator
/// </summary>
public static readonly SyntaxAnnotation Annotation = new(nameof(CodeGenerator));

private static ICodeGenerationService GetCodeGenerationService(HostWorkspaceServices services, string language)
private static ICodeGenerationService GetCodeGenerationService(SolutionServices services, string language)
#if CODE_STYLE
=> services.GetRequiredLanguageService<ICodeGenerationService>(language);
#else
=> services.GetExtendedLanguageServices(language).GetRequiredService<ICodeGenerationService>();

#endif
/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional event of the same signature as the specified event symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddEventDeclarationAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, IEventSymbol @event, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddEventAsync(context, destination, @event, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddEventAsync(context, destination, @event, cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oop restricts access to Workspace. We do not need this here. So this fixes features that use the code-gen service to not crash in OOP.


/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional field of the same signature as the specified field symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddFieldDeclarationAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, IFieldSymbol field, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddFieldAsync(context, destination, field, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddFieldAsync(context, destination, field, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional method of the same signature as the specified method symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddMethodDeclarationAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, IMethodSymbol method, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddMethodAsync(context, destination, method, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddMethodAsync(context, destination, method, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional property of the same signature as the specified property symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddPropertyDeclarationAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, IPropertySymbol property, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddPropertyAsync(context, destination, property, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddPropertyAsync(context, destination, property, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional named type of the same signature as the specified named type symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddNamedTypeDeclarationAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, INamedTypeSymbol namedType, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddNamedTypeAsync(context, destination, namedType, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddNamedTypeAsync(context, destination, namedType, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional named type of the same signature as the specified named type symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddNamedTypeDeclarationAsync(CodeGenerationSolutionContext context, INamespaceSymbol destination, INamedTypeSymbol namedType, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddNamedTypeAsync(context, destination, namedType, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddNamedTypeAsync(context, destination, namedType, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional namespace of the same signature as the specified namespace symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddNamespaceDeclarationAsync(CodeGenerationSolutionContext context, INamespaceSymbol destination, INamespaceSymbol @namespace, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddNamespaceAsync(context, destination, @namespace, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddNamespaceAsync(context, destination, @namespace, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has an additional namespace or type of the same signature as the specified namespace or type symbol.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddNamespaceOrTypeDeclarationAsync(CodeGenerationSolutionContext context, INamespaceSymbol destination, INamespaceOrTypeSymbol namespaceOrType, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddNamespaceOrTypeAsync(context, destination, namespaceOrType, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddNamespaceOrTypeAsync(context, destination, namespaceOrType, cancellationToken);

/// <summary>
/// Create a new solution where the declaration of the destination symbol has additional members of the same signature as the specified member symbols.
/// Returns the document in the new solution where the destination symbol is declared.
/// </summary>
public static Task<Document> AddMemberDeclarationsAsync(CodeGenerationSolutionContext context, INamedTypeSymbol destination, IEnumerable<ISymbol> members, CancellationToken cancellationToken)
=> GetCodeGenerationService(context.Solution.Workspace.Services, destination.Language).AddMembersAsync(context, destination, members, cancellationToken);
=> GetCodeGenerationService(context.Solution.Services, destination.Language).AddMembersAsync(context, destination, members, cancellationToken);

/// <summary>
/// Returns <c>true</c> if additional declarations can be added to the destination symbol's declaration.
/// </summary>
public static bool CanAdd(Solution solution, ISymbol destination, CancellationToken cancellationToken)
=> GetCodeGenerationService(solution.Workspace.Services, destination.Language).CanAddTo(destination, solution, cancellationToken);
=> GetCodeGenerationService(solution.Services, destination.Language).CanAddTo(destination, solution, cancellationToken);
}
Loading