예제 #1
0
        private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol symbol, TypeSyntax type)
        {
            switch (symbol.Kind)
            {
            case SymbolKind.ArrayType:
                var arraySymbol = (IArrayTypeSymbol)symbol;
                AppendQualifiedSymbolName(builder, arraySymbol.ElementType, GetElementSyntax(type));
                builder
                .Append("[")
                .Append(',', arraySymbol.Rank - 1)
                .Append("]");

                AppendNullableSuffixIfNeeded(builder, type);
                return(true);

            case SymbolKind.Namespace:
                var namespaceSymbol = (INamespaceSymbol)symbol;
                if (namespaceSymbol.IsGlobalNamespace)
                {
                    return(false);
                }

                builder.Append(namespaceSymbol.ToDisplayString());
                return(true);

            case SymbolKind.NamedType:
                var namedTypeSymbol = (INamedTypeSymbol)symbol;

                if (SpecialTypeHelper.TryGetPredefinedType(namedTypeSymbol.SpecialType, out var specialTypeSyntax) &&
                    (type?.IsKind(SyntaxKind.PredefinedType) == true ||
                     (type is NullableTypeSyntax nullable && nullable.ElementType.IsKind(SyntaxKind.PredefinedType))))
                {
                    // This handles these cases: int, int?, object, object?
                    // But not these cases: System.Int32, System.Int32?, System.Object, System.Object?
                    builder.Append(specialTypeSyntax.ToFullString());
                    AppendNullableSuffixIfNeeded(builder, type);
                    return(true);
                }
                else if (namedTypeSymbol.IsTupleType())
                {
                    return(AppendTupleType(builder, namedTypeSymbol, type));
                }
                else if (namedTypeSymbol.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T &&
                         type?.IsKind(SyntaxKind.NullableType) == true)
                {
                    // This handles the case '(int, int)?' but not 'System.Nullable<(int, int)>'
                    AppendQualifiedSymbolName(builder, namedTypeSymbol.TypeArguments[0], GetElementSyntax(type));
                    builder.Append("?");
                    return(true);
                }
                else
                {
                    return(AppendNamedType(builder, namedTypeSymbol, type));
                }
        /// <summary>
        /// Generates the qualified name for the given symbol.
        /// </summary>
        /// <param name="symbol">The symbol to use.</param>
        /// <returns>The generated qualified name.</returns>
        public static string ToQualifiedString(this ISymbol symbol)
        {
            var builder = ObjectPools.StringBuilderPool.Allocate();

            if (symbol is INamedTypeSymbol namedTypeSymbol)
            {
                if (SpecialTypeHelper.TryGetPredefinedType(namedTypeSymbol.SpecialType, out PredefinedTypeSyntax specialTypeSyntax))
                {
                    return(specialTypeSyntax.ToFullString());
                }

                if (namedTypeSymbol.IsTupleType())
                {
                    namedTypeSymbol = namedTypeSymbol.TupleUnderlyingType();
                }

                AppendQualifiedSymbolName(builder, namedTypeSymbol);

                if (namedTypeSymbol.IsGenericType)
                {
                    builder.Append(GenericTypeParametersOpen);

                    foreach (var typeArgument in namedTypeSymbol.TypeArguments)
                    {
                        if (typeArgument is INamedTypeSymbol namedTypeArgument && typeArgument.IsTupleType())
                        {
                            builder.Append(namedTypeArgument.TupleUnderlyingType().ToQualifiedString());
                        }
                        else
                        {
                            builder.Append(typeArgument.ToQualifiedString());
                        }

                        builder.Append(GenericSeparator);
                    }

                    builder.Remove(builder.Length - GenericSeparator.Length, GenericSeparator.Length);
                    builder.Append(GenericTypeParametersClose);
                }
예제 #3
0
        private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol symbol, TypeSyntax type)
        {
            switch (symbol.Kind)
            {
            case SymbolKind.ArrayType:
                var arraySymbol = (IArrayTypeSymbol)symbol;
                AppendQualifiedSymbolName(builder, arraySymbol.ElementType, (type as ArrayTypeSyntax)?.ElementType);
                builder
                .Append("[")
                .Append(',', arraySymbol.Rank - 1)
                .Append("]");
                return(true);

            case SymbolKind.Namespace:
                var namespaceSymbol = (INamespaceSymbol)symbol;
                if (namespaceSymbol.IsGlobalNamespace)
                {
                    return(false);
                }

                builder.Append(namespaceSymbol.ToDisplayString());
                return(true);

            case SymbolKind.NamedType:
                var namedTypeSymbol = (INamedTypeSymbol)symbol;
                if (SpecialTypeHelper.TryGetPredefinedType(namedTypeSymbol.SpecialType, out var specialTypeSyntax))
                {
                    builder.Append(specialTypeSyntax.ToFullString());
                    return(true);
                }
                else if (namedTypeSymbol.IsTupleType())
                {
                    if (TupleTypeSyntaxWrapper.IsInstance(type))
                    {
                        var tupleType = (TupleTypeSyntaxWrapper)type;

                        builder.Append(TupleTypeOpen);
                        var elements = namedTypeSymbol.TupleElements();
                        for (int i = 0; i < elements.Length; i++)
                        {
                            var field     = elements[i];
                            var fieldType = tupleType.Elements.Count > i ? tupleType.Elements[i] : default;

                            if (i > 0)
                            {
                                builder.Append(TupleElementSeparator);
                            }

                            AppendQualifiedSymbolName(builder, field.Type, fieldType.Type);
                            if (field != field.CorrespondingTupleField())
                            {
                                builder.Append(" ").Append(field.Name);
                            }
                        }

                        builder.Append(TupleTypeClose);
                        return(true);
                    }
                    else
                    {
                        return(AppendQualifiedSymbolName(builder, namedTypeSymbol.TupleUnderlyingType(), type));
                    }
                }
                else if (namedTypeSymbol.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
                {
                    AppendQualifiedSymbolName(builder, namedTypeSymbol.TypeArguments[0], (type as NullableTypeSyntax)?.ElementType);
                    builder.Append("?");
                    return(true);
                }
                else
                {
                    if (AppendQualifiedSymbolName(builder, symbol.ContainingSymbol, (type as QualifiedNameSyntax)?.Left))
                    {
                        builder.Append(".");
                    }

                    builder.Append(symbol.Name);
                    if (namedTypeSymbol.IsGenericType && !namedTypeSymbol.TypeArguments.IsEmpty)
                    {
                        builder.Append(GenericTypeParametersOpen);
                        var arguments     = namedTypeSymbol.TypeArguments;
                        var argumentTypes = type is QualifiedNameSyntax qualifiedName
                            ? (qualifiedName.Right as GenericNameSyntax)?.TypeArgumentList
                            : (type as GenericNameSyntax)?.TypeArgumentList;

                        for (int i = 0; i < arguments.Length; i++)
                        {
                            var argument     = arguments[i];
                            var argumentType = argumentTypes != null && argumentTypes.Arguments.Count > i ? argumentTypes.Arguments[i] : null;

                            if (i > 0)
                            {
                                builder.Append(GenericSeparator);
                            }

                            if (!argumentType.IsKind(SyntaxKind.OmittedTypeArgument))
                            {
                                AppendQualifiedSymbolName(builder, argument, argumentType);
                            }
                        }

                        builder.Append(GenericTypeParametersClose);
                    }

                    return(true);
                }

            default:
                if (symbol != null)
                {
                    builder.Append(symbol.Name);
                    return(true);
                }

                return(false);
            }
        }