예제 #1
0
        private static IList <SyntaxNode> CreateGetHashCodeMethodStatements(
            ISyntaxFactoryService factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IList <ISymbol> members,
            CancellationToken cancellationToken)
        {
            const string HashCodeName = "hashCode";

            // -1521134295
            var permuteValue = factory.CreateNegateExpression(
                factory.CreateConstantExpression(1521134295));

            var statements = new List <SyntaxNode>();

            var hashCodeNameExpression = factory.CreateIdentifierName(HashCodeName);

            var firstHashValue = ComputeHashValue(factory, compilation, members[0]);

            if (members.Count == 1)
            {
#if false
                return(this.S1.GetHashCode());
#endif
                statements.Add(factory.CreateReturnStatement(firstHashValue));
            }
            else
            {
#if false
                var hashCode = this.S1.GetHashCode();
#endif
                statements.Add(factory.CreateLocalDeclarationStatement(
                                   factory.CreateVariableDeclarator(HashCodeName, firstHashValue)));

                for (var i = 1; i < members.Count; i++)
                {
#if false
                    hashCode = hashCode * 0xA5555529 + value
#endif
                    statements.Add(factory.CreateExpressionStatement(
                                       factory.CreateAssignExpression(hashCodeNameExpression,
                                                                      factory.CreateAddExpression(
                                                                          factory.CreateMultiplyExpression(hashCodeNameExpression, permuteValue),
                                                                          ComputeHashValue(factory, compilation, members[i])))));
                }

#if false
                return(hashCode);
#endif
                statements.Add(factory.CreateReturnStatement(hashCodeNameExpression));
            }

            return(statements);
        }
        private static IList<SyntaxNode> CreateGetHashCodeMethodStatements(
            ISyntaxFactoryService factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IList<ISymbol> members,
            CancellationToken cancellationToken)
        {
            const string HashCodeName = "hashCode";

            // -1521134295
            var permuteValue = factory.CreateNegateExpression(
                factory.CreateConstantExpression(1521134295));

            var statements = new List<SyntaxNode>();

            var hashCodeNameExpression = factory.CreateIdentifierName(HashCodeName);

            var firstHashValue = ComputeHashValue(factory, compilation, members[0]);
            if (members.Count == 1)
            {
#if false
                return this.S1.GetHashCode();
#endif
                statements.Add(factory.CreateReturnStatement(firstHashValue));
            }
            else
            {
#if false
                var hashCode = this.S1.GetHashCode();
#endif
                statements.Add(factory.CreateLocalDeclarationStatement(
                    factory.CreateVariableDeclarator(HashCodeName, firstHashValue)));

                for (var i = 1; i < members.Count; i++)
                {
#if false
                    hashCode = hashCode * 0xA5555529 + value
#endif
                    statements.Add(factory.CreateExpressionStatement(
                        factory.CreateAssignExpression(hashCodeNameExpression,
                            factory.CreateAddExpression(
                                factory.CreateMultiplyExpression(hashCodeNameExpression, permuteValue),
                                ComputeHashValue(factory, compilation, members[i])))));
                }

#if false
                return hashCode;
#endif
                statements.Add(factory.CreateReturnStatement(hashCodeNameExpression));
            }

            return statements;
        }
예제 #3
0
        public static IMethodSymbol OverrideMethod(
            this ISyntaxFactoryService codeFactory,
            IMethodSymbol overriddenMethod,
            SymbolModifiers modifiers,
            INamedTypeSymbol newContainingType,
            Document newDocument,
            CancellationToken cancellationToken)
        {
            // Abstract: Throw not implemented
            if (overriddenMethod.IsAbstract)
            {
                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: new[] { codeFactory.CreateThrowNotImplementStatement(newDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken)) }));
            }
            else
            {
                // Otherwise, call the base method with the same parameters
                var typeParams = overriddenMethod.GetTypeArguments();
                var body       = codeFactory.CreateInvocationExpression(
                    codeFactory.CreateMemberAccessExpression(codeFactory.CreateBaseExpression(),
                                                             typeParams.IsDefaultOrEmpty
                        ? codeFactory.CreateIdentifierName(overriddenMethod.Name)
                        : codeFactory.CreateGenericName(overriddenMethod.Name, typeParams)),
                    codeFactory.CreateArguments(overriddenMethod.GetParameters()));

                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           method: overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: ((IMethodSymbol)overriddenMethod).ReturnsVoid
                        ? new SyntaxNode[] { codeFactory.CreateExpressionStatement(body) }
                        : new SyntaxNode[] { codeFactory.CreateReturnStatement(body) }));
            }
        }
예제 #4
0
        private static IList <SyntaxNode> CreateEqualsMethodStatements(
            ISyntaxFactoryService factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IEnumerable <ISymbol> members,
            CancellationToken cancellationToken)
        {
            var statements = new List <SyntaxNode>();

            var    parts     = StringBreaker.BreakIntoWordParts(containingType.Name);
            string localName = "v";

            for (int i = parts.Count - 1; i >= 0; i--)
            {
                var p = parts[i];
                if (char.IsLetter(containingType.Name[p.Start]))
                {
                    localName = containingType.Name.Substring(p.Start, p.Length).ToCamelCase();
                    break;
                }
            }

            var localNameExpression = factory.CreateIdentifierName(localName);

            var objNameExpression = factory.CreateIdentifierName(ObjName);

            var expressions = new List <SyntaxNode>();

            if (containingType.IsValueType)
            {
#if false
                if (!(obj is MyType))
                {
                    return(false);
                }
#endif
                var ifStatement = factory.CreateIfStatement(
                    factory.CreateLogicalNotExpression(
                        factory.CreateIsExpression(
                            objNameExpression,
                            containingType)),
                    new[] { factory.CreateReturnStatement(factory.CreateFalseExpression()) });

#if false
                var myType = (MyType)obj;
#endif
                var localDeclaration = factory.CreateLocalDeclarationStatement(
                    factory.CreateVariableDeclarator(localName, factory.CreateCastExpression(containingType, objNameExpression)));

                statements.Add(ifStatement);
                statements.Add(localDeclaration);
            }
            else
            {
#if false
                var myType = obj as MyType;
#endif
                var localDeclaration = factory.CreateLocalDeclarationStatement(
                    factory.CreateVariableDeclarator(localName, factory.CreateAsExpression(objNameExpression, containingType)));

                statements.Add(localDeclaration);

#if false
                myType != null
#endif
                expressions.Add(factory.CreateReferenceNotEqualsExpression(localNameExpression, factory.CreateNullExpression()));

                if (HasExistingBaseEqualsMethod(containingType, cancellationToken))
                {
#if false
                    base.Equals(obj)
#endif
                    expressions.Add(factory.CreateInvocationExpression(
                                        factory.CreateMemberAccessExpression(
                                            factory.CreateBaseExpression(),
                                            factory.CreateIdentifierName(EqualsName)),
                                        objNameExpression));
                }
            }

            foreach (var member in members)
            {
                var symbolNameExpression = factory.CreateIdentifierName(member.Name);
                var thisSymbol           = factory.CreateMemberAccessExpression(factory.CreateThisExpression(), symbolNameExpression).WithAdditionalAnnotations(Simplification.Simplifier.Annotation);
                var otherSymbol          = factory.CreateMemberAccessExpression(localNameExpression, symbolNameExpression);

#if false
                EqualityComparer <SType> .Default.Equals(this.S1, myType.S1)
#endif
                var expression =
                    factory.CreateInvocationExpression(
                        factory.CreateMemberAccessExpression(
                            GetDefaultEqualityComparer(factory, compilation, member),
                            factory.CreateIdentifierName(EqualsName)),
                        thisSymbol,
                        otherSymbol);

                expressions.Add(expression);
            }

#if false
            return(myType != null && base.Equals(obj) && EqualityComparer <int> .Default.Equals(this.S1, myType.S1) &&...);
#endif
            statements.Add(factory.CreateReturnStatement(
                               expressions.Aggregate(factory.CreateLogicalAndExpression)));

            return(statements);
        }
        private static IList<SyntaxNode> CreateEqualsMethodStatements(
            ISyntaxFactoryService factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IEnumerable<ISymbol> members,
            CancellationToken cancellationToken)
        {
            var statements = new List<SyntaxNode>();

            var parts = StringBreaker.BreakIntoWordParts(containingType.Name);
            string localName = "v";
            for (int i = parts.Count - 1; i >= 0; i--)
            {
                var p = parts[i];
                if (char.IsLetter(containingType.Name[p.Start]))
                {
                    localName = containingType.Name.Substring(p.Start, p.Length).ToCamelCase();
                    break;
                }
            }

            var localNameExpression = factory.CreateIdentifierName(localName);

            var objNameExpression = factory.CreateIdentifierName(ObjName);

            var expressions = new List<SyntaxNode>();

            if (containingType.IsValueType)
            {
#if false
                if (!(obj is MyType))
                {
                    return false;
                }
#endif
                var ifStatement = factory.CreateIfStatement(
                    factory.CreateLogicalNotExpression(
                        factory.CreateIsExpression(
                            objNameExpression,
                            containingType)),
                    new[] { factory.CreateReturnStatement(factory.CreateFalseExpression()) });

#if false
                var myType = (MyType)obj;
#endif
                var localDeclaration = factory.CreateLocalDeclarationStatement(
                    factory.CreateVariableDeclarator(localName, factory.CreateCastExpression(containingType, objNameExpression)));

                statements.Add(ifStatement);
                statements.Add(localDeclaration);
            }
            else
            {
#if false
                var myType = obj as MyType;
#endif
                var localDeclaration = factory.CreateLocalDeclarationStatement(
                    factory.CreateVariableDeclarator(localName, factory.CreateAsExpression(objNameExpression, containingType)));

                statements.Add(localDeclaration);

#if false
                myType != null
#endif
                expressions.Add(factory.CreateReferenceNotEqualsExpression(localNameExpression, factory.CreateNullExpression()));
                if (HasExistingBaseEqualsMethod(containingType, cancellationToken))
                {
#if false
                    base.Equals(obj)
#endif
                    expressions.Add(factory.CreateInvocationExpression(
                        factory.CreateMemberAccessExpression(
                            factory.CreateBaseExpression(),
                            factory.CreateIdentifierName(EqualsName)),
                        objNameExpression));
                }
            }

            foreach (var member in members)
            {
                var symbolNameExpression = factory.CreateIdentifierName(member.Name);
                var thisSymbol = factory.CreateMemberAccessExpression(factory.CreateThisExpression(), symbolNameExpression).WithAdditionalAnnotations(Simplification.Simplifier.Annotation);
                var otherSymbol = factory.CreateMemberAccessExpression(localNameExpression, symbolNameExpression);

#if false
                EqualityComparer<SType>.Default.Equals(this.S1, myType.S1)
#endif
                var expression =
                    factory.CreateInvocationExpression(
                        factory.CreateMemberAccessExpression(
                            GetDefaultEqualityComparer(factory, compilation, member),
                            factory.CreateIdentifierName(EqualsName)),
                        thisSymbol,
                        otherSymbol);

                expressions.Add(expression);
            }

#if false
            return myType != null && base.Equals(obj) && EqualityComparer<int>.Default.Equals(this.S1, myType.S1) && ...;
#endif
            statements.Add(factory.CreateReturnStatement(
                expressions.Aggregate(factory.CreateLogicalAndExpression)));

            return statements;
        }
예제 #6
0
        public static IPropertySymbol OverrideProperty(
            this ISyntaxFactoryService codeFactory,
            IPropertySymbol overriddenProperty,
            SymbolModifiers modifiers,
            INamedTypeSymbol containingType,
            Document document,
            CancellationToken cancellationToken)
        {
            var getAccessibility = overriddenProperty.GetMethod.ComputeResultantAccessibility(containingType);
            var setAccessibility = overriddenProperty.SetMethod.ComputeResultantAccessibility(containingType);

            SyntaxNode getBody = null;
            SyntaxNode setBody = null;

            // Implement an abstract property by throwing not implemented in accessors.
            if (overriddenProperty.IsAbstract)
            {
                getBody = codeFactory.CreateThrowNotImplementStatement(document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken));
                setBody = getBody;
            }
            else if (overriddenProperty.IsIndexer() && document.Project.Language == LanguageNames.CSharp)
            {
                // Indexer: return or set base[]. Only in C#, since VB must refer to these by name.
                getBody = codeFactory.CreateReturnStatement(
                    codeFactory.CreateElementAccessExpression(
                        codeFactory.CreateBaseExpression(),
                        codeFactory.CreateArguments(overriddenProperty.Parameters)));

                setBody = codeFactory.CreateExpressionStatement(
                    codeFactory.CreateAssignExpression(
                        codeFactory.CreateElementAccessExpression(
                            codeFactory.CreateBaseExpression(),
                            codeFactory.CreateArguments(overriddenProperty.Parameters)),
                        codeFactory.CreateIdentifierName("value")));
            }
            else if (overriddenProperty.GetParameters().Any())
            {
                // Call accessors directly if C# overriding VB
                if (document.Project.Language == LanguageNames.CSharp &&
                    SymbolFinder.FindSourceDefinitionAsync(overriddenProperty, document.Project.Solution)
                    .WaitAndGetResult(CancellationToken.None).Language == LanguageNames.VisualBasic)
                {
                    var getName = overriddenProperty.GetMethod != null ? overriddenProperty.GetMethod.Name : null;
                    var setName = overriddenProperty.SetMethod != null ? overriddenProperty.SetMethod.Name : null;

                    getBody = getName == null
                        ? null
                        : codeFactory.CreateReturnStatement(
                        codeFactory.CreateInvocationExpression(
                            codeFactory.CreateMemberAccessExpression(
                                codeFactory.CreateBaseExpression(),
                                codeFactory.CreateIdentifierName(getName)),
                            codeFactory.CreateArguments(overriddenProperty.Parameters)));

                    setBody = setName == null
                        ? null
                        : codeFactory.CreateExpressionStatement(
                        codeFactory.CreateInvocationExpression(
                            codeFactory.CreateMemberAccessExpression(
                                codeFactory.CreateBaseExpression(),
                                codeFactory.CreateIdentifierName(setName)),
                            codeFactory.CreateArguments(overriddenProperty.SetMethod.GetParameters())));
                }
                else
                {
                    getBody = codeFactory.CreateReturnStatement(
                        codeFactory.CreateInvocationExpression(
                            codeFactory.CreateMemberAccessExpression(
                                codeFactory.CreateBaseExpression(),
                                codeFactory.CreateIdentifierName(overriddenProperty.Name)), codeFactory.CreateArguments(overriddenProperty.Parameters)));
                    setBody = codeFactory.CreateExpressionStatement(
                        codeFactory.CreateAssignExpression(
                            codeFactory.CreateInvocationExpression(
                                codeFactory.CreateMemberAccessExpression(
                                    codeFactory.CreateBaseExpression(),
                                    codeFactory.CreateIdentifierName(overriddenProperty.Name)), codeFactory.CreateArguments(overriddenProperty.Parameters)),
                            codeFactory.CreateIdentifierName("value")));
                }
            }
            else
            {
                // Regular property: return or set the base property
                getBody = codeFactory.CreateReturnStatement(
                    codeFactory.CreateMemberAccessExpression(
                        codeFactory.CreateBaseExpression(),
                        codeFactory.CreateIdentifierName(overriddenProperty.Name)));
                setBody = codeFactory.CreateExpressionStatement(
                    codeFactory.CreateAssignExpression(
                        codeFactory.CreateMemberAccessExpression(
                            codeFactory.CreateBaseExpression(),
                            codeFactory.CreateIdentifierName(overriddenProperty.Name)),
                        codeFactory.CreateIdentifierName("value")));
            }

            // Only generate a getter if the base getter is accessible.
            IMethodSymbol accessorGet = null;

            if (overriddenProperty.GetMethod != null && overriddenProperty.GetMethod.IsAccessibleWithin(containingType))
            {
                accessorGet = CodeGenerationSymbolFactory.CreateMethodSymbol(
                    overriddenProperty.GetMethod,
                    accessibility: getAccessibility,
                    statements: new[] { getBody },
                    modifiers: modifiers);
            }

            // Only generate a setter if the base setter is accessible.
            IMethodSymbol accessorSet = null;

            if (overriddenProperty.SetMethod != null &&
                overriddenProperty.SetMethod.IsAccessibleWithin(containingType) &&
                overriddenProperty.SetMethod.DeclaredAccessibility != Accessibility.Private)
            {
                accessorSet = CodeGenerationSymbolFactory.CreateMethodSymbol(
                    overriddenProperty.SetMethod,
                    accessibility: setAccessibility,
                    statements: new[] { setBody },
                    modifiers: modifiers);
            }

            return(CodeGenerationSymbolFactory.CreatePropertySymbol(
                       overriddenProperty,
                       accessibility: overriddenProperty.ComputeResultantAccessibility(containingType),
                       modifiers: modifiers,
                       name: overriddenProperty.Name,
                       isIndexer: overriddenProperty.IsIndexer(),
                       getMethod: accessorGet,
                       setMethod: accessorSet));
        }