private async Task <ChangeSignatureAnalyzedContext> GetContextAsync( Document document, int position, bool restrictToDeclarations, CancellationToken cancellationToken) { var symbol = await GetInvocationSymbolAsync( document, position, restrictToDeclarations, cancellationToken).ConfigureAwait(false); // Cross-lang symbols will show as metadata, so map it to source if possible. symbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, cancellationToken).ConfigureAwait(false) ?? symbol; if (symbol == null) { return(new ChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } if (symbol is IMethodSymbol) { var method = symbol as IMethodSymbol; var containingType = method.ContainingType; if (method.Name == WellKnownMemberNames.DelegateBeginInvokeName && containingType != null && containingType.IsDelegateType() && containingType.DelegateInvokeMethod != null) { symbol = containingType.DelegateInvokeMethod; } } if (symbol is IEventSymbol) { symbol = (symbol as IEventSymbol).Type; } if (symbol is INamedTypeSymbol) { var typeSymbol = symbol as INamedTypeSymbol; if (typeSymbol.IsDelegateType() && typeSymbol.DelegateInvokeMethod != null) { symbol = typeSymbol.DelegateInvokeMethod; } } if (symbol.Locations.Any(loc => loc.IsInMetadata)) { return(new ChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DefinedInMetadata)); } if (!symbol.MatchesKind(SymbolKind.Method, SymbolKind.Property, SymbolKind.NamedType)) { return(new ChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } var parameterConfiguration = ParameterConfiguration.Create(symbol.GetParameters().ToList(), symbol is IMethodSymbol && (symbol as IMethodSymbol).IsExtensionMethod); if (!parameterConfiguration.IsChangeable()) { return(new ChangeSignatureAnalyzedContext(CannotChangeSignatureReason.InsufficientParameters)); } return(new ChangeSignatureAnalyzedContext( document.Project, symbol, parameterConfiguration)); }
internal async Task <ChangeSignatureAnalyzedContext> GetContextAsync( Document document, int position, bool restrictToDeclarations, CancellationToken cancellationToken) { var(symbol, selectedIndex) = await GetInvocationSymbolAsync( document, position, restrictToDeclarations, cancellationToken).ConfigureAwait(false); // Cross-language symbols will show as metadata, so map it to source if possible. symbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, cancellationToken).ConfigureAwait(false) ?? symbol; if (symbol == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } if (symbol is IMethodSymbol method) { var containingType = method.ContainingType; if (method.Name == WellKnownMemberNames.DelegateBeginInvokeName && containingType != null && containingType.IsDelegateType() && containingType.DelegateInvokeMethod != null) { symbol = containingType.DelegateInvokeMethod; } } if (symbol is IEventSymbol ev) { symbol = ev.Type; } if (symbol is INamedTypeSymbol typeSymbol) { if (typeSymbol.IsDelegateType() && typeSymbol.DelegateInvokeMethod != null) { symbol = typeSymbol.DelegateInvokeMethod; } } if (!symbol.MatchesKind(SymbolKind.Method, SymbolKind.Property)) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } if (symbol.Locations.Any(loc => loc.IsInMetadata)) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DefinedInMetadata)); } // This should be called after the metadata check above to avoid looking for nodes in metadata. var declarationLocation = symbol.Locations.FirstOrDefault(); if (declarationLocation == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DefinedInMetadata)); } var solution = document.Project.Solution; var declarationDocument = solution.GetRequiredDocument(declarationLocation.SourceTree !); var declarationChangeSignatureService = declarationDocument.GetRequiredLanguageService <AbstractChangeSignatureService>(); int insertPosition; var reference = symbol.DeclaringSyntaxReferences.FirstOrDefault(); if (reference != null) { insertPosition = declarationChangeSignatureService.GetPositionBeforeParameterListClosingBrace(reference.GetSyntax()); } else { // There may be no declaring syntax reference, for example delegate Invoke methods. Use an // insertPosition of 0 and continue on. insertPosition = 0; } var parameterConfiguration = ParameterConfiguration.Create( symbol.GetParameters().Select(p => new ExistingParameter(p)).ToImmutableArray <Parameter>(), symbol.IsExtensionMethod(), selectedIndex); return(new ChangeSignatureAnalysisSucceededContext( declarationDocument, insertPosition, symbol, parameterConfiguration)); }
internal async Task <ChangeSignatureAnalyzedContext> GetContextAsync( Document document, int position, bool restrictToDeclarations, CancellationToken cancellationToken) { var(symbol, selectedIndex) = await GetInvocationSymbolAsync( document, position, restrictToDeclarations, cancellationToken).ConfigureAwait(false); // Cross-language symbols will show as metadata, so map it to source if possible. symbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, cancellationToken).ConfigureAwait(false) ?? symbol; if (symbol == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } if (symbol is IMethodSymbol method) { var containingType = method.ContainingType; if (method.Name == WellKnownMemberNames.DelegateBeginInvokeName && containingType != null && containingType.IsDelegateType() && containingType.DelegateInvokeMethod != null) { symbol = containingType.DelegateInvokeMethod; } } if (symbol is IEventSymbol ev) { symbol = ev.Type; } if (symbol is INamedTypeSymbol typeSymbol) { if (typeSymbol.IsDelegateType() && typeSymbol.DelegateInvokeMethod != null) { symbol = typeSymbol.DelegateInvokeMethod; } } if (symbol.Locations.Any(loc => loc.IsInMetadata)) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DefinedInMetadata)); } // This should be called after the metadata check above to avoid looking for nodes in metadata. var declarationLocation = symbol.Locations.FirstOrDefault(); if (declarationLocation == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DefinedInMetadata)); } var solution = document.Project.Solution; var documentId = solution.GetDocumentId(declarationLocation.SourceTree); var declarationDocument = solution.GetDocument(documentId); var declarationChangeSignatureService = declarationDocument?.GetRequiredLanguageService <AbstractChangeSignatureService>(); if (declarationChangeSignatureService == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DeclarationLanguageServiceNotFound)); } int?insertPositionOpt = declarationChangeSignatureService.TryGetInsertPositionFromDeclaration(symbol.Locations.FirstOrDefault().FindNode(cancellationToken)); if (insertPositionOpt == null) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.DeclarationMethodPositionNotFound)); } if (!symbol.MatchesKind(SymbolKind.Method, SymbolKind.Property, SymbolKind.NamedType)) { return(new CannotChangeSignatureAnalyzedContext(CannotChangeSignatureReason.IncorrectKind)); } var parameterConfiguration = ParameterConfiguration.Create( symbol.GetParameters().Select(p => new ExistingParameter(p)), symbol.IsExtensionMethod(), selectedIndex); return(new ChangeSignatureAnalyzedSucceedContext( declarationDocument ?? document, insertPositionOpt.Value, symbol, parameterConfiguration)); }