public override void VisitMethod(IMethodSymbol symbol) { if (symbol.MethodKind == MethodKind.AnonymousFunction) { // TODO(cyrusn): Why is this a literal? Why don't we give the appropriate signature // of the method as asked? builder.Add(CreatePart(SymbolDisplayPartKind.NumericLiteral, symbol, "lambda expression")); return; } else if (symbol is SynthesizedGlobalMethodSymbol) // It would be nice to handle VB symbols too, but it's not worth the effort. { // Represents a compiler generated synthesized method symbol with a null containing // type. // TODO(cyrusn); Why is this a literal? builder.Add(CreatePart(SymbolDisplayPartKind.NumericLiteral, symbol, symbol.Name)); return; } if (symbol.IsExtensionMethod && format.ExtensionMethodStyle != SymbolDisplayExtensionMethodStyle.Default) { if (symbol.MethodKind == MethodKind.ReducedExtension && format.ExtensionMethodStyle == SymbolDisplayExtensionMethodStyle.StaticMethod) { symbol = symbol.GetConstructedReducedFrom(); } else if (symbol.MethodKind != MethodKind.ReducedExtension && format.ExtensionMethodStyle == SymbolDisplayExtensionMethodStyle.InstanceMethod) { // If we cannot reduce this to an instance form then display in the static form symbol = symbol.ReduceExtensionMethod(symbol.Parameters.First().Type) ?? symbol; } } // Method members always have a type unless (1) this is a lambda method symbol, which we // have dealt with already, or (2) this is an error method symbol. If we have an error method // symbol then we do not know its accessibility, modifiers, etc, all of which require knowing // the containing type, so we'll skip them. if ((object)symbol.ContainingType != null || (symbol.ContainingSymbol is ITypeSymbol)) { AddAccessibilityIfRequired(symbol); AddMemberModifiersIfRequired(symbol); if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeType)) { switch (symbol.MethodKind) { case MethodKind.Constructor: case MethodKind.StaticConstructor: break; case MethodKind.Destructor: case MethodKind.Conversion: // If we're using the metadata format, then include the return type. // Otherwise we eschew it since it is redundant in an conversion // signature. if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames)) { goto default; } break; default: // The display code is called by the debugger; if a developer is debugging Roslyn and attempts // to visualize a symbol *during its construction*, the parameters and return type might // still be null. if (symbol.ReturnsByRef) { AddRefIfRequired(); } else if (symbol.ReturnsByRefReadonly) { AddRefReadonlyIfRequired(); } AddCustomModifiersIfRequired(symbol.RefCustomModifiers); if (symbol.ReturnsVoid) { AddKeyword(SyntaxKind.VoidKeyword); } else if (symbol.ReturnType != null) { AddReturnType(symbol); } AddSpace(); AddCustomModifiersIfRequired(symbol.ReturnTypeCustomModifiers); break; } } if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeContainingType)) { ITypeSymbol containingType; bool includeType; if (symbol.MethodKind == MethodKind.LocalFunction) { includeType = false; containingType = null; } else if (symbol.MethodKind == MethodKind.ReducedExtension) { containingType = symbol.ReceiverType; includeType = true; Debug.Assert(containingType != null); } else { containingType = symbol.ContainingType; if ((object)containingType != null) { includeType = IncludeNamedType(symbol.ContainingType); } else { containingType = (ITypeSymbol)symbol.ContainingSymbol; includeType = true; } } if (includeType) { containingType.Accept(this.NotFirstVisitor); AddPunctuation(SyntaxKind.DotToken); } } } bool isAccessor = false; switch (symbol.MethodKind) { case MethodKind.Ordinary: case MethodKind.DelegateInvoke: case MethodKind.ReducedExtension: case MethodKind.LocalFunction: //containing type will be the delegate type, name will be Invoke builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, symbol.Name)); break; case MethodKind.PropertyGet: case MethodKind.PropertySet: isAccessor = true; var associatedProperty = (IPropertySymbol)symbol.AssociatedSymbol; if (associatedProperty == null) { goto case MethodKind.Ordinary; } AddPropertyNameAndParameters(associatedProperty); AddPunctuation(SyntaxKind.DotToken); AddKeyword(symbol.MethodKind == MethodKind.PropertyGet ? SyntaxKind.GetKeyword : SyntaxKind.SetKeyword); break; case MethodKind.EventAdd: case MethodKind.EventRemove: isAccessor = true; var associatedEvent = (IEventSymbol)symbol.AssociatedSymbol; if (associatedEvent == null) { goto case MethodKind.Ordinary; } AddEventName(associatedEvent); AddPunctuation(SyntaxKind.DotToken); AddKeyword(symbol.MethodKind == MethodKind.EventAdd ? SyntaxKind.AddKeyword : SyntaxKind.RemoveKeyword); break; case MethodKind.Constructor: case MethodKind.StaticConstructor: // Note: we are using the metadata name also in the case that // symbol.containingType is null (which should never be the case here) or is an // anonymous type (which 'does not have a name'). var name = format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames) || symbol.ContainingType == null || symbol.ContainingType.IsAnonymousType ? symbol.Name : symbol.ContainingType.Name; builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, name)); break; case MethodKind.Destructor: // Note: we are using the metadata name also in the case that symbol.containingType is null, which should never be the case here. if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames) || symbol.ContainingType == null) { builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, symbol.Name)); } else { AddPunctuation(SyntaxKind.TildeToken); builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, symbol.ContainingType.Name)); } break; case MethodKind.ExplicitInterfaceImplementation: AddExplicitInterfaceIfRequired(symbol.ExplicitInterfaceImplementations); builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(symbol.Name))); break; case MethodKind.UserDefinedOperator: case MethodKind.BuiltinOperator: if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames)) { builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, symbol.MetadataName)); } else { AddKeyword(SyntaxKind.OperatorKeyword); AddSpace(); if (symbol.MetadataName == WellKnownMemberNames.TrueOperatorName) { AddKeyword(SyntaxKind.TrueKeyword); } else if (symbol.MetadataName == WellKnownMemberNames.FalseOperatorName) { AddKeyword(SyntaxKind.FalseKeyword); } else { builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, SyntaxFacts.GetText(SyntaxFacts.GetOperatorKind(symbol.MetadataName)))); } } break; case MethodKind.Conversion: if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames)) { builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, symbol.MetadataName)); } else { // "System.IntPtr.explicit operator System.IntPtr(int)" if (symbol.MetadataName == WellKnownMemberNames.ExplicitConversionName) { AddKeyword(SyntaxKind.ExplicitKeyword); } else if (symbol.MetadataName == WellKnownMemberNames.ImplicitConversionName) { AddKeyword(SyntaxKind.ImplicitKeyword); } else { builder.Add(CreatePart(SymbolDisplayPartKind.MethodName, symbol, SyntaxFacts.GetText(SyntaxFacts.GetOperatorKind(symbol.MetadataName)))); } AddSpace(); AddKeyword(SyntaxKind.OperatorKeyword); AddSpace(); AddReturnType(symbol); } break; default: throw ExceptionUtilities.UnexpectedValue(symbol.MethodKind); } if (!isAccessor) { AddTypeArguments(symbol, default(ImmutableArray <ImmutableArray <CustomModifier> >)); AddParameters(symbol); AddTypeParameterConstraints(symbol); } }