Beispiel #1
0
 /// <summary>
 /// Make a generic type from arguments.
 /// </summary>
 /// <param name="baseType">The base type.</param>
 /// <param name="arguments">The arguments.</param>
 /// <returns>The generic type.</returns>
 public static INamedTypeSymbol MakeGeneric(this INamedTypeSymbol baseType, TypedConstant arguments)
 {
     if (arguments.Values.Length > 0)
     {
         return(baseType.Construct(arguments.Values.Select(v => v.Value).Cast <INamedTypeSymbol>().ToArray()));
     }
     if (arguments.Value is INamedTypeSymbol arg)
     {
         return(baseType.Construct(arg));
     }
     return(null);
 }
        private SyntaxNode FixMethod(
            bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method,
            ITypeSymbol taskType, INamedTypeSymbol taskOfTType)
        {
            var newReturnType = method.ReturnType;

            if (methodSymbol.ReturnsVoid)
            {
                if (!keepVoid)
                {
                    newReturnType = taskType.GenerateTypeSyntax();
                }
            }
            else
            {
                if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType))
                {
                    // If it's not already Task-like, then wrap the existing return type
                    // in Task<>.
                    newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax();
                }
            }

            var newModifiers = method.Modifiers.Add(s_asyncToken);
            return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
        }
Beispiel #3
0
        private SyntaxNode FixMethod(
            bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method,
            INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType)
        {
            var newReturnType = method.ReturnType;

            if (methodSymbol.ReturnsVoid)
            {
                if (!keepVoid)
                {
                    newReturnType = taskType.GenerateTypeSyntax();
                }
            }
            else
            {
                if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType, valueTaskOfTType))
                {
                    // If it's not already Task-like, then wrap the existing return type
                    // in Task<>.
                    newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax();
                }
            }

            var newModifiers = method.Modifiers.Add(s_asyncToken);

            return(method.WithReturnType(newReturnType).WithModifiers(newModifiers));
        }
Beispiel #4
0
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;

            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            bool overridesObjectEquals = namedType.OverridesEquals();

            INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType);
            INamedTypeSymbol implementation       = namedType
                                                    .Interfaces
                                                    .Where(x => x.Equals(constructedEquatable))
                                                    .FirstOrDefault();
            bool implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_implementIEquatableDescriptor, namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_overridesObjectEqualsDescriptor, namedType));
            }
        }
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;

            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            var methodSymbol = namedType
                               .GetMembers("Equals")
                               .OfType <IMethodSymbol>()
                               .Where(m => IsObjectEqualsOverride(m, objectType))
                               .FirstOrDefault();
            var overridesObjectEquals = methodSymbol != null;

            var constructedEquatable = equatableType.Construct(namedType);
            var implementation       = namedType
                                       .Interfaces
                                       .Where(x => x.Equals(constructedEquatable))
                                       .FirstOrDefault();
            var implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_implementIEquatableDescriptor, methodSymbol.Locations[0], namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_overridesObjectEqualsDescriptor, namedType.Locations[0], namedType));
            }
        }
        private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;
            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            bool overridesObjectEquals = namedType.OverridesEquals();

            INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType);
            INamedTypeSymbol implementation = namedType
                .Interfaces
                .Where(x => x.Equals(constructedEquatable))
                .FirstOrDefault();
            bool implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_implementIEquatableDescriptor, namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_overridesObjectEqualsDescriptor, namedType));
            }
        }
        private static TypeSyntax FixMethodReturnType(
            bool keepVoid, IMethodSymbol methodSymbol, TypeSyntax returnType,
            INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType)
        {
            var newReturnType = returnType;

            if (methodSymbol.ReturnsVoid)
            {
                if (!keepVoid)
                {
                    newReturnType = taskType.GenerateTypeSyntax();
                }
            }
            else
            {
                if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType, valueTaskOfTType))
                {
                    // If it's not already Task-like, then wrap the existing return type
                    // in Task<>.
                    newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax();
                }
            }

            return(newReturnType.WithTriviaFrom(returnType));
        }
Beispiel #8
0
        public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol?typeArgument, [NotNullWhen(returnValue: true)] INamedTypeSymbol?interfaceType, string interfaceMethodName)
        {
            INamedTypeSymbol?constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType;

            return(constructedInterface?.GetMembers(interfaceMethodName).FirstOrDefault() is IMethodSymbol interfaceMethod &&
                   SymbolEqualityComparer.Default.Equals(method, method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
        }
Beispiel #9
0
 public static INamedTypeSymbol Construct(
     this INamedTypeSymbol definition,
     params TypeSymbol[] typeArguments
     )
 {
     return(definition.Construct(typeArguments.Select(s => s.GetPublicSymbol()).ToArray()));
 }
        private static bool TryGetGenericType(
            Compilation compilation,
            INamedTypeSymbol genericTypeDefinition,
            ImmutableArray <string> genericTypeArguments,
            out INamedTypeSymbol genericType
            )
        {
            INamedTypeSymbol[] genericTypeArgumentSymbols = new INamedTypeSymbol[genericTypeArguments.Length];

            for (int i = 0; i < genericTypeArguments.Length; i++)
            {
                string genericTypeArgumentName = genericTypeArguments[i];

                INamedTypeSymbol genericTypeArgumentSymbol = compilation.GetTypeByMetadataName(genericTypeArgumentName);
                if (genericTypeArgumentSymbol.IsNullOrErrorType())
                {
                    genericType = null;
                    return(false);
                }

                genericTypeArgumentSymbols[i] = genericTypeArgumentSymbol;
            }

            genericType = genericTypeDefinition.Construct(genericTypeArgumentSymbols);
            if (genericType.IsNullOrErrorType())
            {
                genericType = null;
                return(false);
            }

            return(true);
        }
Beispiel #11
0
        private static async Task <Document> ImplementEquatableInStructAsync(Document document, SyntaxNode declaration,
                                                                             INamedTypeSymbol typeSymbol, Compilation compilation, INamedTypeSymbol equatableType,
                                                                             CancellationToken cancellationToken)
        {
            var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            var generator = editor.Generator;

            var equalsMethod = generator.MethodDeclaration(
                WellKnownMemberNames.ObjectEquals,
                new[]
            {
                generator.ParameterDeclaration("other", generator.TypeExpression(typeSymbol))
            },
                returnType: generator.TypeExpression(SpecialType.System_Boolean),
                accessibility: Accessibility.Public,
                statements: generator.DefaultMethodBody(compilation));

            editor.AddMember(declaration, equalsMethod);

            INamedTypeSymbol constructedType = equatableType.Construct(typeSymbol);

            editor.AddInterfaceType(declaration, generator.TypeExpression(constructedType));

            return(editor.GetChangedDocument());
        }
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;
            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            var methodSymbol = namedType
                .GetMembers("Equals")
                .OfType<IMethodSymbol>()
                .Where(m => IsObjectEqualsOverride(m, objectType))
                .FirstOrDefault();
            var overridesObjectEquals = methodSymbol != null;

            var constructedEquatable = equatableType.Construct(namedType);
            var implementation = namedType
                .Interfaces
                .Where(x => x.Equals(constructedEquatable))
                .FirstOrDefault();
            var implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_implementIEquatableDescriptor, methodSymbol.Locations[0], namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_overridesObjectEqualsDescriptor, namedType.Locations[0], namedType));
            }
        }
Beispiel #13
0
        private static ITypeSymbol GetMemberNewType(
            ISymbol memberSymbol,
            ITypeSymbol memberTypeSymbol,
            ExpressionSyntax expression,
            ITypeSymbol expressionSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (memberSymbol.IsAsyncMethod())
            {
                if (expression.IsKind(SyntaxKind.AwaitExpression))
                {
                    var awaitExpression = (AwaitExpressionSyntax)expression;

                    if (awaitExpression.Expression != null)
                    {
                        var awaitableSymbol = semanticModel.GetTypeSymbol(awaitExpression.Expression, cancellationToken) as INamedTypeSymbol;

                        if (awaitableSymbol != null)
                        {
                            INamedTypeSymbol taskOfTSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T);

                            if (awaitableSymbol.ConstructedFrom.Equals(taskOfTSymbol))
                            {
                                return(awaitableSymbol);
                            }
                        }
                    }
                }
                else if (memberTypeSymbol.IsNamedType())
                {
                    INamedTypeSymbol taskOfTSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T);

                    if (((INamedTypeSymbol)memberTypeSymbol).ConstructedFrom.Equals(taskOfTSymbol))
                    {
                        if (expressionSymbol.IsNamedType() &&
                            ((INamedTypeSymbol)expressionSymbol).ConstructedFrom.Equals(taskOfTSymbol))
                        {
                            return(null);
                        }

                        INamedTypeSymbol taskSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task);

                        if (expressionSymbol.Equals(taskSymbol))
                        {
                            return(null);
                        }

                        return(taskOfTSymbol.Construct(expressionSymbol));
                    }
                }
            }
            else
            {
                return(expressionSymbol);
            }

            return(null);
        }
Beispiel #14
0
        /// <summary>
        /// Checks if the given method is an implementation of the given interface method
        /// Substituted with the given typeargument.
        /// </summary>
        public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol typeArgument, INamedTypeSymbol interfaceType, string interfaceMethodName)
        {
            INamedTypeSymbol constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType;

            var interfaceMethod = constructedInterface?.GetMembers(interfaceMethodName).Single() as IMethodSymbol;

            return(interfaceMethod != null && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
        }
Beispiel #15
0
        public static async Task ComputeRefactoringAsync(RefactoringContext context, StructDeclarationSyntax structDeclaration)
        {
            SyntaxToken identifier = structDeclaration.Identifier;

            if (identifier.IsMissing)
            {
                return;
            }

            TextSpan span = identifier.Span;

            BaseListSyntax baseList = structDeclaration.BaseList;

            if (baseList != null)
            {
                span = TextSpan.FromBounds(span.Start, baseList.Span.End);
            }

            TypeParameterListSyntax typeParameterList = structDeclaration.TypeParameterList;

            if (typeParameterList != null)
            {
                span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End);
            }

            if (!span.Contains(context.Span))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(structDeclaration, context.CancellationToken);

            if (typeSymbol?.IsErrorType() != false)
            {
                return;
            }

            INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_IEquatable_T);

            if (equatableSymbol == null)
            {
                return;
            }

            equatableSymbol = equatableSymbol.Construct(typeSymbol);

            if (typeSymbol.Implements(equatableSymbol, allInterfaces: true))
            {
                return;
            }

            context.RegisterRefactoring(
                GetTitle(equatableSymbol, semanticModel, structDeclaration.SpanStart),
                f => RefactorAsync(context.Document, structDeclaration, typeSymbol, equatableSymbol, semanticModel, f),
                RefactoringIdentifiers.ImplementIEquatableOfT);
        }
Beispiel #16
0
        private static bool TypeImplementsEquatable(INamedTypeSymbol type, INamedTypeSymbol equatableType)
        {
            INamedTypeSymbol constructedEquatable = equatableType.Construct(type);
            INamedTypeSymbol implementation       = type
                                                    .Interfaces
                                                    .FirstOrDefault(x => x.Equals(constructedEquatable));

            return(implementation != null);
        }
Beispiel #17
0
        private static bool ImplementsIEquatable(ITypeSymbol memberType, INamedTypeSymbol iequatableType)
        {
            if (iequatableType != null)
            {
                var constructed = iequatableType.Construct(memberType);
                return(memberType.AllInterfaces.Contains(constructed));
            }

            return(false);
        }
Beispiel #18
0
        private static Maybe <Case.ClassCase> CreateClassCase(
            INamedTypeSymbol doClassSymbol,
            INamedTypeSymbol subClassSymbol)
        {
            var containingType = subClassSymbol.ContainingType;

            var openDoClassSymbol = doClassSymbol.IsGenericType ? doClassSymbol.ConstructedFrom : doClassSymbol;

            if (containingType == null)
            {
                if (subClassSymbol.TypeParameters.Length != doClassSymbol.TypeParameters.Length)
                {
                    return(Maybe.NoValue);
                }

                var baseTypeOfSubClass = subClassSymbol.BaseType;

                if (baseTypeOfSubClass.IsGenericType && baseTypeOfSubClass.TypeArguments.Any(x => x.Kind != SymbolKind.TypeParameter))
                {
                    return(Maybe.NoValue);
                }

                if (!doClassSymbol.IsGenericType || doClassSymbol.IsUnboundGenericType)
                {
                    return(new Case.ClassCase(subClassSymbol));
                }

                return(new Case.ClassCase(subClassSymbol.Construct(doClassSymbol.TypeArguments.ToArray())));
            }

            if (containingType.Equals(openDoClassSymbol))
            {
                if (HasTypeParameters(subClassSymbol))
                {
                    return(Maybe.NoValue);
                }

                if (!openDoClassSymbol.IsGenericType || openDoClassSymbol.IsUnboundGenericType)
                {
                    return(new Case.ClassCase(subClassSymbol));
                }


                var namedTypeSymbol = doClassSymbol.GetMembers()
                                      .OfType <INamedTypeSymbol>().Single(x => x.OriginalDefinition.Equals(subClassSymbol));
                return(new Case.ClassCase(
                           namedTypeSymbol));
            }

            return(Maybe.NoValue);
        }
Beispiel #19
0
 private static SyntaxNode GetReturnStatementForExplicitClass(SyntaxGenerator generator,
                                                              INamedTypeSymbol typeSymbol, SyntaxNode argumentName, INamedTypeSymbol equatableType)
 {
     return(generator.ReturnStatement(
                generator.InvocationExpression(
                    generator.MemberAccessExpression(
                        generator.CastExpression(
                            equatableType.Construct(typeSymbol),
                            generator.ThisExpression()),
                        WellKnownMemberNames.ObjectEquals),
                    generator.TryCastExpression(
                        argumentName,
                        typeSymbol))));
 }
Beispiel #20
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out SyntaxNode node, predicate: f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement)))
            {
                return;
            }

            Diagnostic diagnostic = context.Diagnostics[0];

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(node, context.CancellationToken);

            Debug.Assert(methodSymbol != null, node.Kind().ToString());

            ITypeSymbol typeSymbol = methodSymbol.ReturnType;

            if (typeSymbol.IsErrorType())
            {
                return;
            }

            (bool containsReturnAwait, bool containsAwaitStatement) = AnalyzeAwaitExpressions(node);

            Debug.Assert(containsAwaitStatement || containsReturnAwait, node.ToString());

            if (containsAwaitStatement)
            {
                INamedTypeSymbol taskSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task);

                CodeFixRegistrator.ChangeReturnType(context, diagnostic, node, taskSymbol, semanticModel, "Task");
            }

            if (containsReturnAwait)
            {
                INamedTypeSymbol taskOfT = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T);

                typeSymbol = taskOfT.Construct(typeSymbol);

                CodeFixRegistrator.ChangeReturnType(context, diagnostic, node, typeSymbol, semanticModel, "TaskOfT");
            }
        }
        public static async Task ComputeRefactoringAsync(RefactoringContext context, ClassDeclarationSyntax classDeclaration)
        {
            SyntaxToken identifier = classDeclaration.Identifier;

            if (!identifier.IsMissing)
            {
                TextSpan span = identifier.Span;

                BaseListSyntax baseList = classDeclaration.BaseList;

                if (baseList != null)
                {
                    span = TextSpan.FromBounds(span.Start, baseList.Span.End);
                }

                TypeParameterListSyntax typeParameterList = classDeclaration.TypeParameterList;

                if (typeParameterList != null)
                {
                    span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End);
                }

                if (span.Contains(context.Span))
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    INamedTypeSymbol classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken);

                    if (classSymbol?.IsErrorType() == false &&
                        !classSymbol.IsStatic)
                    {
                        INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_IEquatable_T);

                        if (equatableSymbol != null)
                        {
                            equatableSymbol = equatableSymbol.Construct(classSymbol);

                            if (!classSymbol.Implements(equatableSymbol))
                            {
                                context.RegisterRefactoring(
                                    GetTitle(equatableSymbol, semanticModel, classDeclaration.SpanStart),
                                    f => RefactorAsync(context.Document, classDeclaration, classSymbol, equatableSymbol, semanticModel, f));
                            }
                        }
                    }
                }
            }
        }
        protected override SyntaxNode AddAsyncKeywordAndTaskReturnType(SyntaxNode node, ITypeSymbol existingReturnType, INamedTypeSymbol taskTypeSymbol)
        {
            var methodNode = node as MethodDeclarationSyntax;

            if (methodNode == null)
            {
                return(null);
            }

            if (taskTypeSymbol == null)
            {
                return(null);
            }

            var returnType = taskTypeSymbol.Construct(existingReturnType).GenerateTypeSyntax();

            return(AddAsyncKeyword(methodNode.WithReturnType(returnType)));
        }
Beispiel #23
0
        private static bool HasExplicitEqualsImplementation(INamedTypeSymbol typeSymbol, INamedTypeSymbol equatableType)
        {
            INamedTypeSymbol constructedType         = equatableType.Construct(typeSymbol);
            IMethodSymbol    constructedEqualsMethod = constructedType.GetMembers().OfType <IMethodSymbol>().Single();

            foreach (IMethodSymbol method in typeSymbol.GetMembers().OfType <IMethodSymbol>())
            {
                foreach (IMethodSymbol explicitImplementation in method.ExplicitInterfaceImplementations)
                {
                    if (explicitImplementation.Equals(constructedEqualsMethod))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #24
0
        private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol equatableType)
        {
            if (!(context.Symbol is INamedTypeSymbol namedType) ||
                (namedType.TypeKind != TypeKind.Struct && namedType.TypeKind != TypeKind.Class) ||
                (namedType.TypeKind == TypeKind.Struct && namedType.IsRefLikeType))
            {
                return;
            }

            bool overridesObjectEquals = namedType.OverridesEquals();

            INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType);
            INamedTypeSymbol implementation       = namedType
                                                    .AllInterfaces
                                                    .FirstOrDefault(x => x.Equals(constructedEquatable));
            bool implementsEquatable = implementation != null;

            if (implementsEquatable)
            {
                // Bail out for following cases:
                // 1. There is no method implementing IEquatable.Equals method, indicating compiler error.
                // 2. Base type is implementing the IEquatable for this type, and hence is responsible for overriding object Equals.
                //    For example, we should not flag type B below as IEquatable<B> is implemented by its base type:
                //       class B : A<B> { }
                //       class A<T> : IEquatable<T>
                //          where T: A<T>
                //       { ... }
                if (!(constructedEquatable.GetMembers("Equals").FirstOrDefault() is IMethodSymbol equatableEqualsMethod) ||
                    !Equals(namedType, namedType.FindImplementationForInterfaceMember(equatableEqualsMethod)?.ContainingType))
                {
                    return;
                }
            }

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(ImplementIEquatableDescriptor, namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(OverridesObjectEqualsDescriptor, namedType));
            }
        }
        public static INamedTypeSymbol GetTypeSymbol(this Type type, Compilation compilation)
        {
            string basicType = type.GetFullTypeStr();

            INamedTypeSymbol namedTypeSymbol = compilation.GetTypeByMetadataName(basicType);

            IEnumerable <Type> genericArgs = type.GetGenericArguments();

            if (genericArgs.IsNullOrEmpty())
            {
                return(namedTypeSymbol);
            }

            INamedTypeSymbol[] genericArgsTypeSymbols =
                genericArgs.Select(genArg => genArg.GetTypeSymbol(compilation)).ToArray();

            namedTypeSymbol = namedTypeSymbol.Construct(genericArgsTypeSymbols);

            return(namedTypeSymbol);
        }
        private static INamedTypeSymbol ConstructActionOrFunc(
            ITypeSymbol returnType,
            ImmutableArray <IParameterSymbol> parameters,
            SemanticModel semanticModel)
        {
            int length = parameters.Length;

            if (returnType.IsVoid())
            {
                if (length == 0)
                {
                    return(semanticModel.GetTypeByMetadataName("System.Action"));
                }

                INamedTypeSymbol actionSymbol = semanticModel.GetTypeByMetadataName($"System.Action`{length.ToString()}");

                var typeArguments = new ITypeSymbol[length];

                for (int i = 0; i < length; i++)
                {
                    typeArguments[i] = parameters[i].Type;
                }

                return(actionSymbol.Construct(typeArguments));
            }
            else
            {
                INamedTypeSymbol funcSymbol = semanticModel.GetTypeByMetadataName($"System.Func`{(length + 1).ToString()}");

                var typeArguments = new ITypeSymbol[length + 1];

                for (int i = 0; i < length; i++)
                {
                    typeArguments[i] = parameters[i].Type;
                }

                typeArguments[length] = returnType;

                return(funcSymbol.Construct(typeArguments));
            }
        }
Beispiel #27
0
        public static ITypeSymbol?GetSymbolForType(this Compilation compilation, Type type)
        {
            if (type.FullName == null)
            {
                return(null);
            }

            if (!type.IsGenericType)
            {
                return(compilation.GetTypeByMetadataName(type.FullName));
            }

            Type genericType = type.GetGenericTypeDefinition();

            Type[] genericArgs = type.GetGenericArguments();

            INamedTypeSymbol genericTypeSymbol = compilation.GetTypeByMetadataName(genericType.FullName !) !;

            ITypeSymbol[] genericArgSymbols = genericArgs.Select(t => compilation.GetSymbolForType(t) !).ToArray();

            return(genericTypeSymbol.Construct(genericArgSymbols));
        }
        public static void ComputeCodeFix(
            CodeFixContext context,
            Diagnostic diagnostic,
            ExpressionSyntax expression,
            SemanticModel semanticModel)
        {
            TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken);

            ITypeSymbol expressionTypeSymbol = typeInfo.Type;

            if (expressionTypeSymbol == null)
            {
                return;
            }

            if (!expressionTypeSymbol.SupportsExplicitDeclaration())
            {
                return;
            }

            (ISymbol symbol, ITypeSymbol typeSymbol) = GetContainingSymbolAndType(expression, semanticModel, context.CancellationToken);

            Debug.Assert(symbol != null, expression.ToString());

            if (symbol == null)
            {
                return;
            }

            if (symbol.IsOverride)
            {
                return;
            }

            if (symbol.ImplementsInterfaceMember())
            {
                return;
            }

            SyntaxNode node = symbol.GetSyntax(context.CancellationToken);

            if (node.Kind() == SyntaxKind.VariableDeclarator)
            {
                node = node.Parent.Parent;
            }

            TypeSyntax type = CSharpUtility.GetTypeOrReturnType(node);

            if (type == null)
            {
                return;
            }

            ITypeSymbol newTypeSymbol = expressionTypeSymbol;

            string additionalKey = null;

            bool isAsyncMethod = false;
            bool insertAwait   = false;
            bool isYield       = false;

            if (symbol.IsAsyncMethod())
            {
                isAsyncMethod = true;

                INamedTypeSymbol taskOfT = semanticModel.GetTypeByMetadataName("System.Threading.Tasks.Task`1");

                if (taskOfT == null)
                {
                    return;
                }

                if (expression.Kind() == SyntaxKind.AwaitExpression)
                {
                    newTypeSymbol = taskOfT.Construct(expressionTypeSymbol);
                }
                else if (expressionTypeSymbol.OriginalDefinition.Equals(taskOfT))
                {
                    insertAwait   = true;
                    additionalKey = "InsertAwait";
                }
                else if (expressionTypeSymbol.HasMetadataName(MetadataNames.System_Threading_Tasks_Task))
                {
                    return;
                }
            }
            else if (expression.IsParentKind(SyntaxKind.YieldReturnStatement))
            {
                isYield = true;

                newTypeSymbol = semanticModel
                                .Compilation
                                .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)
                                .Construct(expressionTypeSymbol);
            }

            if (!isYield &&
                !isAsyncMethod &&
                !typeSymbol.OriginalDefinition.IsIEnumerableOfT() &&
                newTypeSymbol.OriginalDefinition.HasMetadataName(MetadataNames.System_Linq_IOrderedEnumerable_T))
            {
                INamedTypeSymbol constructedEnumerableSymbol = semanticModel
                                                               .Compilation
                                                               .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)
                                                               .Construct(((INamedTypeSymbol)newTypeSymbol).TypeArguments.ToArray());

                RegisterCodeFix(context, diagnostic, node, type, expression, constructedEnumerableSymbol, semanticModel, insertAwait: false);
                additionalKey = "IOrderedEnumerable<T>";
            }

            RegisterCodeFix(context, diagnostic, node, type, expression, newTypeSymbol, semanticModel, insertAwait: insertAwait, additionalKey: additionalKey);
        }
Beispiel #29
0
 public static INamedTypeSymbol TryConstruct(this INamedTypeSymbol type, ITypeSymbol[] typeArguments)
 => typeArguments.Length > 0 ? type.Construct(typeArguments) : type;
 public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments)
 => namedType.Construct(typeArguments);
Beispiel #31
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, ExpressionSyntax expression)
        {
            if (expression != null)
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                ISymbol memberSymbol = GetContainingMethodOrPropertySymbol(expression, semanticModel, context.CancellationToken);

                if (memberSymbol != null)
                {
                    SyntaxNode node = await memberSymbol
                                      .DeclaringSyntaxReferences[0]
                                      .GetSyntaxAsync(context.CancellationToken)
                                      .ConfigureAwait(false);

                    var declaration = node as MemberDeclarationSyntax;

                    if (declaration != null)
                    {
                        TypeSyntax memberType = GetMemberType(declaration);

                        if (memberType != null)
                        {
                            ITypeSymbol memberTypeSymbol = semanticModel.GetTypeSymbol(memberType, context.CancellationToken);

                            if (memberTypeSymbol != null)
                            {
                                ITypeSymbol expressionSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken);

                                if (expressionSymbol?.IsErrorType() == false)
                                {
                                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeMemberTypeAccordingToReturnExpression))
                                    {
                                        ITypeSymbol newType = GetMemberNewType(memberSymbol, memberTypeSymbol, expression, expressionSymbol, semanticModel, context.CancellationToken);

                                        if (newType?.IsErrorType() == false &&
                                            !memberTypeSymbol.Equals(newType) &&
                                            !memberSymbol.IsOverride &&
                                            !memberSymbol.ImplementsInterfaceMember())
                                        {
                                            if (newType.IsNamedType() && memberTypeSymbol.IsNamedType())
                                            {
                                                var newNamedType = (INamedTypeSymbol)newType;

                                                INamedTypeSymbol orderedEnumerableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Linq_IOrderedEnumerable_T);

                                                if (newNamedType.ConstructedFrom == orderedEnumerableSymbol)
                                                {
                                                    INamedTypeSymbol enumerableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Collections_Generic_IEnumerable_T);

                                                    if (enumerableSymbol != null &&
                                                        ((INamedTypeSymbol)memberTypeSymbol).ConstructedFrom != enumerableSymbol)
                                                    {
                                                        RegisterChangeType(context, declaration, memberType, enumerableSymbol.Construct(newNamedType.TypeArguments.ToArray()), semanticModel);
                                                    }
                                                }
                                            }

                                            RegisterChangeType(context, declaration, memberType, newType, semanticModel);
                                        }
                                    }

                                    if (context.IsAnyRefactoringEnabled(RefactoringIdentifiers.AddCastExpression, RefactoringIdentifiers.CallToMethod) &&
                                        !memberTypeSymbol.IsErrorType())
                                    {
                                        ITypeSymbol castTypeSymbol = GetCastTypeSymbol(memberSymbol, memberTypeSymbol, expressionSymbol, semanticModel);

                                        if (castTypeSymbol != null)
                                        {
                                            ModifyExpressionRefactoring.ComputeRefactoring(
                                                context,
                                                expression,
                                                castTypeSymbol,
                                                semanticModel);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #32
0
        private static void AddMissingMembersToStatefulMarshaller(DocumentEditor editor, SyntaxNode declaringSyntax, INamedTypeSymbol marshallerType, ITypeSymbol managedType, HashSet <string> missingMemberNames, bool isLinearCollectionMarshaller)
        {
            SyntaxGenerator gen = editor.Generator;

            // Get the methods of the shape so we can use them to determine what types to use in signatures that are not obvious.
            var(_, methods) = StatefulMarshallerShapeHelper.GetShapeForType(marshallerType, managedType, isLinearCollectionMarshaller, editor.SemanticModel.Compilation);
            INamedTypeSymbol spanOfT         = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_Span_Metadata) !;
            INamedTypeSymbol readOnlySpanOfT = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata) !;

            var(typeParameters, _) = marshallerType.GetAllTypeArgumentsIncludingInContainingTypes();

            // Use a lazy factory for the type syntaxes to avoid re-checking the various methods and reconstructing the syntax.
            Lazy <SyntaxNode>  unmanagedTypeSyntax      = new(CreateUnmanagedTypeSyntax, isThreadSafe : false);
            Lazy <ITypeSymbol> managedElementTypeSymbol = new(CreateManagedElementTypeSymbol, isThreadSafe : false);

            List <SyntaxNode> newMembers = new();

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromManaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.FromManaged,
                        parameters: new[] { gen.ParameterDeclaration("managed", gen.TypeExpression(managedType)) },
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToUnmanaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.ToUnmanaged,
                        returnType: unmanagedTypeSyntax.Value,
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromUnmanaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.FromUnmanaged,
                        parameters: new[] { gen.ParameterDeclaration("unmanaged", unmanagedTypeSyntax.Value) },
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToManaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.ToManaged,
                        returnType: gen.TypeExpression(managedType),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.BufferSize))
            {
                newMembers.Add(
                    gen.WithAccessorDeclarations(
                        gen.PropertyDeclaration(ShapeMemberNames.BufferSize,
                                                gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_Int32)),
                                                Accessibility.Public,
                                                DeclarationModifiers.Static),
                        gen.GetAccessorDeclaration(statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource,
                        returnType: gen.TypeExpression(readOnlySpanOfT.Construct(managedElementTypeSymbol.Value)),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination,
                        returnType: gen.TypeExpression(spanOfT.Construct(typeParameters[typeParameters.Length - 1])),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource,
                        parameters: new[]
                {
                    gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32))
                },
                        returnType: gen.TypeExpression(readOnlySpanOfT.Construct(typeParameters[typeParameters.Length - 1])),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination,
                        parameters: new[]
                {
                    gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32))
                },
                        returnType: gen.TypeExpression(spanOfT.Construct(managedElementTypeSymbol.Value)),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Free))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.Free,
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            editor.ReplaceNode(declaringSyntax, (declaringSyntax, gen) => gen.AddMembers(declaringSyntax, newMembers));

            SyntaxNode CreateUnmanagedTypeSyntax()
            {
                ITypeSymbol?unmanagedType = null;

                if (methods.ToUnmanaged is not null)
                {
                    unmanagedType = methods.ToUnmanaged.ReturnType;
                }
                else if (methods.FromUnmanaged is not null)
                {
                    unmanagedType = methods.FromUnmanaged.Parameters[0].Type;
                }
                else if (methods.UnmanagedValuesSource is not null)
                {
                    unmanagedType = methods.UnmanagedValuesSource.Parameters[0].Type;
                }
                else if (methods.UnmanagedValuesDestination is not null)
                {
                    unmanagedType = methods.UnmanagedValuesDestination.Parameters[0].Type;
                }

                if (unmanagedType is not null)
                {
                    return(gen.TypeExpression(unmanagedType));
                }
                return(gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr)));
            }

            ITypeSymbol CreateManagedElementTypeSymbol()
            {
                if (methods.ManagedValuesSource is not null)
                {
                    return(((INamedTypeSymbol)methods.ManagedValuesSource.ReturnType).TypeArguments[0]);
                }
                if (methods.ManagedValuesDestination is not null)
                {
                    return(((INamedTypeSymbol)methods.ManagedValuesDestination.ReturnType).TypeArguments[0]);
                }

                return(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr));
            }
        }
 public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments)
 {
     return(namedType.Construct(typeArguments));
 }
        protected override SyntaxNode AddAsyncKeywordAndTaskReturnType(SyntaxNode node, ITypeSymbol existingReturnType, INamedTypeSymbol taskTypeSymbol)
        {
            var methodNode = node as MethodDeclarationSyntax;
            if (methodNode == null)
            {
                return null;
            }

            if (taskTypeSymbol == null)
            {
                return null;
            }

            var returnType = taskTypeSymbol.Construct(existingReturnType).GenerateTypeSyntax();
            return AddAsyncKeyword(methodNode.WithReturnType(returnType));
        }
 public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments)
 {
     return namedType.Construct(typeArguments);
 }