public static async Task <Document> ConvertToTopLevelStatementsAsync( Document document, MethodDeclarationSyntax methodDeclaration, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var typeDeclaration = (TypeDeclarationSyntax?)methodDeclaration.Parent; Contract.ThrowIfNull(typeDeclaration); // checked by analyzer var generator = document.GetRequiredLanguageService <SyntaxGenerator>(); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var rootWithGlobalStatements = GetRootWithGlobalStatements( semanticModel, generator, root, typeDeclaration, methodDeclaration, cancellationToken); // simple case. we were in a top level type to begin with. Nothing we need to do now. if (typeDeclaration.Parent is not BaseNamespaceDeclarationSyntax namespaceDeclaration) { return(document.WithSyntaxRoot(rootWithGlobalStatements)); } // We were parented by a namespace. Add using statements to bring in all the symbols that were // previously visible within the namespace. Then remove any that we don't need once we've done that. var cleanupOptions = await document.GetCodeCleanupOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); document = await AddUsingDirectivesAsync( document, rootWithGlobalStatements, namespaceDeclaration, cleanupOptions, cancellationToken).ConfigureAwait(false); // if we have a file scoped namespace after converting to top-level-statements, then convert it to a // block-namespace. Top level statements and file-scoped-namespaces are not allowed together. document = await ConvertFileScopedNamespaceAsync(document, cancellationToken).ConfigureAwait(false); return(document); }
public SymbolInlineRenameInfo( IEnumerable <IRefactorNotifyService> refactorNotifyServices, Document document, TextSpan triggerSpan, string triggerText, ISymbol renameSymbol, bool forceRenameOverloads, ImmutableArray <DocumentSpan> definitionLocations, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { this.CanRename = true; _refactorNotifyServices = refactorNotifyServices; _document = document; _fallbackOptions = fallbackOptions; this.RenameSymbol = renameSymbol; this.HasOverloads = RenameLocations.GetOverloadedSymbols(this.RenameSymbol).Any(); this.MustRenameOverloads = forceRenameOverloads; _isRenamingAttributePrefix = CanRenameAttributePrefix(triggerText); this.TriggerSpan = GetReferenceEditSpan(new InlineRenameLocation(document, triggerSpan), triggerText, cancellationToken); this.DefinitionLocations = definitionLocations; }
public ChangeSignatureAnalysisSucceededContext( Document document, int positionForTypeBinding, ISymbol symbol, ParameterConfiguration parameterConfiguration, CodeCleanupOptionsProvider fallbackOptions) { Document = document; Symbol = symbol; ParameterConfiguration = parameterConfiguration; PositionForTypeBinding = positionForTypeBinding; FallbackOptions = fallbackOptions; }
private static async Task <RenameLocations> FindLocationsInCurrentProcessAsync( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider cleanupOptions, CancellationToken cancellationToken) { Contract.ThrowIfNull(symbol); using (Logger.LogBlock(FunctionId.Rename_AllRenameLocations, cancellationToken)) { symbol = await ReferenceProcessing.FindDefinitionSymbolAsync(symbol, solution, cancellationToken).ConfigureAwait(false); // First, find the direct references just to the symbol being renamed. var originalSymbolResult = await AddLocationsReferenceSymbolsAsync(symbol, solution, cancellationToken).ConfigureAwait(false); // Next, find references to overloads, if the user has asked to rename those as well. var overloadsResult = options.RenameOverloads ? await GetOverloadsAsync(symbol, solution, cancellationToken).ConfigureAwait(false) : ImmutableArray <SearchResult> .Empty; // Finally, include strings/comments if that's what the user wants. var(strings, comments) = await ReferenceProcessing.GetRenamableLocationsInStringsAndCommentsAsync( symbol, solution, originalSymbolResult.Locations, options.RenameInStrings, options.RenameInComments, cancellationToken).ConfigureAwait(false); var mergedLocations = ImmutableHashSet.CreateBuilder <RenameLocation>(); using var _1 = ArrayBuilder <ISymbol> .GetInstance(out var mergedReferencedSymbols); using var _2 = ArrayBuilder <ReferenceLocation> .GetInstance(out var mergedImplicitLocations); var renameMethodGroupReferences = options.RenameOverloads || !GetOverloadedSymbols(symbol).Any(); foreach (var result in overloadsResult.Concat(originalSymbolResult)) { mergedLocations.AddRange(renameMethodGroupReferences ? result.Locations : result.Locations.Where(x => x.CandidateReason != CandidateReason.MemberGroup)); mergedImplicitLocations.AddRange(result.ImplicitLocations); mergedReferencedSymbols.AddRange(result.ReferencedSymbols); } // Add string and comment locations to the merged hashset // after adding in reference symbols. This allows any references // in comments to be resolved as proper references rather than // comment resolutions. See https://github.com/dotnet/roslyn/issues/54294 mergedLocations.AddRange(strings.NullToEmpty()); mergedLocations.AddRange(comments.NullToEmpty()); return(new RenameLocations( symbol, solution, options, cleanupOptions, new SearchResult( mergedLocations.ToImmutable(), mergedImplicitLocations.ToImmutable(), mergedReferencedSymbols.ToImmutable()))); } }
internal static RenameLocations Create( ImmutableHashSet <RenameLocation> locations, ISymbol symbol, Solution solution, ImmutableArray <ISymbol> referencedSymbols, ImmutableArray <ReferenceLocation> implicitLocations, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions) { return(new RenameLocations( symbol, solution, options, fallbackOptions, new SearchResult(locations, implicitLocations, referencedSymbols))); }
private RenameLocations( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, SearchResult result) { Solution = solution; Symbol = symbol; Options = options; FallbackOptions = fallbackOptions; _result = result; }
internal static State Generate( SemanticDocument document, TTypeDeclarationSyntax typeDeclaration, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var state = new State(document, fallbackOptions); if (!state.TryInitialize(typeDeclaration, cancellationToken)) { return(null); } return(state); }
public ExtractInterfaceTypeAnalysisResult( Document documentToExtractFrom, SyntaxNode typeNode, INamedTypeSymbol typeToExtractFrom, IEnumerable <ISymbol> extractableMembers, CodeCleanupOptionsProvider fallbackOptions) { CanExtractInterface = true; DocumentToExtractFrom = documentToExtractFrom; TypeNode = typeNode; TypeToExtractFrom = typeToExtractFrom; ExtractableMembers = extractableMembers; FallbackOptions = fallbackOptions; }
public override async Task <ImmutableArray <CodeAction> > GetRefactoringAsync( Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var state = await CreateStateAsync(document, textSpan, fallbackOptions, cancellationToken).ConfigureAwait(false); if (state == null) { return(ImmutableArray <CodeAction> .Empty); } var actions = CreateActions(state, cancellationToken); return(actions); }
/// <summary> /// Find the locations that need to be renamed. Can cross process boundaries efficiently to do this. /// </summary> public static async Task <LightweightRenameLocations> FindRenameLocationsAsync( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { Contract.ThrowIfNull(solution); Contract.ThrowIfNull(symbol); cancellationToken.ThrowIfCancellationRequested(); using (Logger.LogBlock(FunctionId.Renamer_FindRenameLocationsAsync, cancellationToken)) { if (SerializableSymbolAndProjectId.TryCreate(symbol, solution, cancellationToken, out var serializedSymbol)) { var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false); if (client != null) { var result = await client.TryInvokeAsync <IRemoteRenamerService, SerializableRenameLocations?>( solution, (service, solutionInfo, callbackId, cancellationToken) => service.FindRenameLocationsAsync(solutionInfo, callbackId, serializedSymbol, options, cancellationToken), callbackTarget : new RemoteOptionsProvider <CodeCleanupOptions>(solution.Workspace.Services, fallbackOptions), cancellationToken).ConfigureAwait(false); if (result.HasValue && result.Value != null) { var rehydrated = await TryRehydrateAsync( solution, symbol, fallbackOptions, result.Value, cancellationToken).ConfigureAwait(false); if (rehydrated != null) { return(rehydrated); } } // TODO: do not fall back to in-proc if client is available (https://github.com/dotnet/roslyn/issues/47557) } } } // Couldn't effectively search in OOP. Perform the search in-proc. var renameLocations = await HeavyweightRenameLocations.FindLocationsInCurrentProcessAsync( symbol, solution, options, fallbackOptions, cancellationToken).ConfigureAwait(false); return(new LightweightRenameLocations( symbol, solution, options, fallbackOptions, renameLocations.Locations, renameLocations.ImplicitLocations.IsDefault ? null : renameLocations.ImplicitLocations.Select(loc => SerializableReferenceLocation.Dehydrate(loc, cancellationToken)).ToArray(), renameLocations.ReferencedSymbols.IsDefault ? null : renameLocations.ReferencedSymbols.Select(sym => SerializableSymbolAndProjectId.Dehydrate(solution, sym, cancellationToken)).ToArray())); }
private LightweightRenameLocations( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, ImmutableHashSet <RenameLocation> locations, SerializableReferenceLocation[]?implicitLocations, SerializableSymbolAndProjectId[]?referencedSymbols) { Symbol = symbol; Solution = solution; Options = options; FallbackOptions = fallbackOptions; Contract.ThrowIfNull(locations); Locations = locations; _implicitLocations = implicitLocations; _referencedSymbols = referencedSymbols; }
public HeavyweightRenameLocations( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, ImmutableHashSet <RenameLocation> locations, ImmutableArray <ReferenceLocation> implicitLocations, ImmutableArray <ISymbol> referencedSymbols) { Solution = solution; Symbol = symbol; Options = options; FallbackOptions = fallbackOptions; Contract.ThrowIfNull(locations); Locations = locations; ReferencedSymbols = referencedSymbols; ImplicitLocations = implicitLocations; }
private static async Task <Solution> RenameAsync( Solution solution, IFieldSymbol field, string finalName, Func <DocumentId, TextSpan, bool> filter, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var options = new SymbolRenameOptions( RenameOverloads: false, RenameInStrings: false, RenameInComments: false, RenameFile: false); var initialLocations = await Renamer.FindRenameLocationsAsync( solution, field, options, fallbackOptions, cancellationToken).ConfigureAwait(false); var resolution = await initialLocations.Filter(filter).ResolveConflictsAsync( field, finalName, nonConflictSymbolKeys: default, cancellationToken).ConfigureAwait(false);
public async Task <ExtractInterfaceTypeAnalysisResult> AnalyzeTypeAtPositionAsync( Document document, int position, TypeDiscoveryRule typeDiscoveryRule, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var typeNode = await GetTypeDeclarationAsync(document, position, typeDiscoveryRule, cancellationToken).ConfigureAwait(false); if (typeNode == null) { var errorMessage = FeaturesResources.Could_not_extract_interface_colon_The_selection_is_not_inside_a_class_interface_struct; return(new ExtractInterfaceTypeAnalysisResult(errorMessage)); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var type = semanticModel.GetDeclaredSymbol(typeNode, cancellationToken); if (type == null || type.Kind != SymbolKind.NamedType) { var errorMessage = FeaturesResources.Could_not_extract_interface_colon_The_selection_is_not_inside_a_class_interface_struct; return(new ExtractInterfaceTypeAnalysisResult(errorMessage)); } var typeToExtractFrom = type as INamedTypeSymbol; var extractableMembers = typeToExtractFrom.GetMembers().Where(IsExtractableMember); if (!extractableMembers.Any()) { var errorMessage = FeaturesResources.Could_not_extract_interface_colon_The_type_does_not_contain_any_member_that_can_be_extracted_to_an_interface; return(new ExtractInterfaceTypeAnalysisResult(errorMessage)); } return(new ExtractInterfaceTypeAnalysisResult(document, typeNode, typeToExtractFrom, extractableMembers, fallbackOptions)); }
private static async Task <Solution> RenameAsync( Solution solution, IFieldSymbol field, string finalName, Func <Location, bool> filter, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var options = new SymbolRenameOptions( RenameOverloads: false, RenameInStrings: false, RenameInComments: false, RenameFile: false); var initialLocations = await Renamer.FindRenameLocationsAsync( solution, field, options, fallbackOptions, cancellationToken).ConfigureAwait(false); var resolution = await initialLocations.Filter(filter).ResolveConflictsAsync( finalName, nonConflictSymbols: null, cancellationToken).ConfigureAwait(false); Contract.ThrowIfTrue(resolution.ErrorMessage != null); return(resolution.NewSolution); }
public static AbstractMoveToNamespaceCodeAction Generate(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult, CodeCleanupOptionsProvider cleanupOptions) => analysisResult.Container switch {
public override async Task <Solution> GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var state = await CreateStateAsync(document, textSpan, fallbackOptions, cancellationToken).ConfigureAwait(false); if (state == null) { return(document.Project.Solution); } var suggestedFileNames = GetSuggestedFileNames( state.TypeNode, IsNestedType(state.TypeNode), state.TypeName, state.SemanticDocument.Document.Name, state.SemanticDocument.SemanticModel, cancellationToken); var editor = Editor.GetEditor(operationKind, (TService)this, state, suggestedFileNames.FirstOrDefault(), cancellationToken); var modifiedSolution = await editor.GetModifiedSolutionAsync().ConfigureAwait(false); return(modifiedSolution ?? document.Project.Solution); }
public static SyncNamespaceDocumentAction?TryCreate(Document document, IReadOnlyList <string> newFolders, CodeCleanupOptionsProvider fallbackOptions) { var analysisResult = Analyze(document, newFolders); if (analysisResult.HasValue) { return(new SyncNamespaceDocumentAction(analysisResult.Value, fallbackOptions)); } return(null); }
public AbstractMoveToNamespaceCodeAction(IMoveToNamespaceService moveToNamespaceService, MoveToNamespaceAnalysisResult analysisResult, CodeCleanupOptionsProvider cleanupOptions) { _moveToNamespaceService = moveToNamespaceService; _moveToNamespaceAnalysisResult = analysisResult; _cleanupOptions = cleanupOptions; }
public MoveTypeToNamespaceCodeAction(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult, CodeCleanupOptionsProvider cleanupOptions) : base(changeNamespaceService, analysisResult, cleanupOptions) { }
public static async ValueTask <CodeCleanupOptions> GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) => await document.GetCodeCleanupOptionsAsync(await ((OptionsProvider <CodeCleanupOptions>)fallbackOptionsProvider).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false);
public async Task <ImmutableArray <ExtractInterfaceCodeAction> > GetExtractInterfaceCodeActionAsync(Document document, TextSpan span, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var typeAnalysisResult = await AnalyzeTypeAtPositionAsync(document, span.Start, TypeDiscoveryRule.TypeNameOnly, fallbackOptions, cancellationToken).ConfigureAwait(false); return(typeAnalysisResult.CanExtractInterface ? ImmutableArray.Create(new ExtractInterfaceCodeAction(this, typeAnalysisResult)) : ImmutableArray <ExtractInterfaceCodeAction> .Empty); }
private async Task <Solution> UpdateReferencesAsync( bool updateReferences, Solution solution, Document document, IFieldSymbol field, string finalFieldName, string generatedPropertyName, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { if (!updateReferences) { return(solution); } var projectId = document.Project.Id; if (field.IsReadOnly) { // Inside the constructor we want to rename references the field to the final field name. var constructorLocations = GetConstructorLocations(solution, field.ContainingType); if (finalFieldName != field.Name && constructorLocations.Count > 0) { solution = await RenameAsync( solution, field, finalFieldName, (docId, span) => IntersectsWithAny(docId, span, constructorLocations), fallbackOptions, cancellationToken).ConfigureAwait(false); document = solution.GetDocument(document.Id); var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); field = field.GetSymbolKey(cancellationToken).Resolve(compilation, cancellationToken: cancellationToken).Symbol as IFieldSymbol; constructorLocations = GetConstructorLocations(solution, field.ContainingType); } // Outside the constructor we want to rename references to the field to final property name. return(await RenameAsync( solution, field, generatedPropertyName, (documentId, span) => !IntersectsWithAny(documentId, span, constructorLocations), fallbackOptions, cancellationToken).ConfigureAwait(false)); } else { // Just rename everything. return(await Renamer.RenameSymbolAsync( solution, field, new SymbolRenameOptions(), generatedPropertyName, cancellationToken).ConfigureAwait(false)); } }
private async Task <State> CreateStateAsync(Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var nodeToAnalyze = await GetRelevantNodeAsync(document, textSpan, cancellationToken).ConfigureAwait(false); if (nodeToAnalyze == null) { return(null); } var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); return(State.Generate(semanticDocument, nodeToAnalyze, fallbackOptions, cancellationToken)); }
private State(SemanticDocument document, CodeCleanupOptionsProvider fallbackOptions) { SemanticDocument = document; FallbackOptions = fallbackOptions; }
private SyncNamespaceDocumentAction(AnalysisResult analysis, CodeCleanupOptionsProvider fallbackOptions) : base(ImmutableArray <ErrorResource> .Empty) { _analysis = analysis; _fallbackOptions = fallbackOptions; }
public abstract Task <Solution?> TryChangeTopLevelNamespacesAsync(Document document, string targetNamespace, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken);
public abstract Task <Solution> ChangeNamespaceAsync(Document document, SyntaxNode container, string targetNamespace, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken);