Example #1
0
 /// <summary>
 /// Get the individual words in the parameter name.  This way we can generate
 /// appropriate field/property names based on the user's preference.
 /// </summary>
 private List <string> GetParameterWordParts(IParameterSymbol parameter)
 {
     using (var breaks = StringBreaker.BreakIntoWordParts(parameter.Name))
     {
         return(CreateWords(breaks, parameter.Name));
     }
 }
            internal static ImmutableArray <IEnumerable <string> > GetBaseNames(ITypeSymbol type)
            {
                var baseName = TryRemoveInterfacePrefix(type);
                var breaks   = StringBreaker.BreakIntoWordParts(baseName);

                return(GetInterleavedPatterns(breaks, baseName));
            }
Example #3
0
        public static string GetLocalName(this INamedTypeSymbol containingType)
        {
            var parts = StringBreaker.BreakIntoWordParts(containingType.Name);

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

            return("v");
        }
Example #4
0
        private static ImmutableArray <SyntaxNode> CreateEqualsMethodStatements(
            SyntaxGenerator factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IEnumerable <ISymbol> members,
            CancellationToken cancellationToken)
        {
            var iequatableType = compilation.GetTypeByMetadataName("System.IEquatable`1");
            var statements     = ArrayBuilder <SyntaxNode> .GetInstance();

            // Come up with a good name for the local variable we're going to compare against.
            // For example, if the class name is "CustomerOrder" then we'll generate:
            //
            //      var order = obj as CustomerOrder;

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

            for (var 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.IdentifierName(localName);

            var objNameExpression = factory.IdentifierName(ObjName);

            // These will be all the expressions that we'll '&&' together inside the final
            // return statement of 'Equals'.
            var expressions = new List <SyntaxNode>();

            if (containingType.IsValueType)
            {
                // If we're a value type, then we need an is-check first to make sure
                // the object is our type:
                //
                //      if (!(obj is MyType))
                //      {
                //          return false;
                //      }
                var ifStatement = factory.IfStatement(
                    factory.LogicalNotExpression(
                        factory.IsTypeExpression(
                            objNameExpression,
                            containingType)),
                    new[] { factory.ReturnStatement(factory.FalseLiteralExpression()) });

                // Next, we cast the argument to our type:
                //
                //      var myType = (MyType)obj;

                var localDeclaration = factory.LocalDeclarationStatement(localName, factory.CastExpression(containingType, objNameExpression));

                statements.Add(ifStatement);
                statements.Add(localDeclaration);
            }
            else
            {
                // It's not a value type, we can just use "as" to test the parameter is the right type:
                //
                //      var myType = obj as MyType;

                var localDeclaration = factory.LocalDeclarationStatement(localName, factory.TryCastExpression(objNameExpression, containingType));

                statements.Add(localDeclaration);

                // Ensure that the parameter we got was not null (which also ensures the 'as' test
                // succeeded):
                //
                //      myType != null
                expressions.Add(factory.ReferenceNotEqualsExpression(localNameExpression, factory.NullLiteralExpression()));
                if (HasExistingBaseEqualsMethod(containingType, cancellationToken))
                {
                    // If we're overriding something that also provided an overridden 'Equals',
                    // then ensure the base type thinks it is equals as well.
                    //
                    //      base.Equals(obj)
                    expressions.Add(factory.InvocationExpression(
                                        factory.MemberAccessExpression(
                                            factory.BaseExpression(),
                                            factory.IdentifierName(EqualsName)),
                                        objNameExpression));
                }
            }

            // Now, iterate over all the supplied members and ensure that our instance
            // and the parameter think they are equals.  Specialize how we do this for
            // common types.  Fall-back to EqualityComparer<SType>.Default.Equals for
            // everything else.
            foreach (var member in members)
            {
                var symbolNameExpression = factory.IdentifierName(member.Name);
                var thisSymbol           = factory.MemberAccessExpression(factory.ThisExpression(), symbolNameExpression)
                                           .WithAdditionalAnnotations(Simplification.Simplifier.Annotation);
                var otherSymbol = factory.MemberAccessExpression(localNameExpression, symbolNameExpression);

                var memberType = member.GetSymbolType();

                if (IsPrimitiveValueType(memberType))
                {
                    // If we have one of the well known primitive types, then just use '==' to compare
                    // the values.
                    //
                    //      this.a == other.a
                    expressions.Add(factory.ValueEqualsExpression(thisSymbol, otherSymbol));
                    continue;
                }

                var valueIEquatable = memberType?.IsValueType == true && ImplementsIEquatable(memberType, iequatableType);
                if (valueIEquatable || memberType?.IsTupleType == true)
                {
                    // If it's a value type and implements IEquatable<T>, Or if it's a tuple, then
                    // just call directly into .Equals. This keeps the code simple and avoids an
                    // unnecessary null check.
                    //
                    //      this.a.Equals(other.a)
                    expressions.Add(factory.InvocationExpression(
                                        factory.MemberAccessExpression(thisSymbol, nameof(object.Equals)),
                                        otherSymbol));
                    continue;
                }

                // Otherwise call EqualityComparer<SType>.Default.Equals(this.a, other.a).
                // This will do the appropriate null checks as well as calling directly
                // into IEquatable<T>.Equals implementations if available.

                expressions.Add(factory.InvocationExpression(
                                    factory.MemberAccessExpression(
                                        GetDefaultEqualityComparer(factory, compilation, member),
                                        factory.IdentifierName(EqualsName)),
                                    thisSymbol,
                                    otherSymbol));
            }

            // Now combine all the comparison expressions together into one final statement like:
            //
            //      return myType != null &&
            //             base.Equals(obj) &&
            //             this.S1 == myType.S1;
            statements.Add(factory.ReturnStatement(
                               expressions.Aggregate(factory.LogicalAndExpression)));

            return(statements.ToImmutableAndFree());
        }
Example #5
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);
        }
Example #6
0
 private static IList <string> BreakIntoWordParts(string identifier)
 {
     return(PartListToSubstrings(identifier, StringBreaker.BreakIntoWordParts(identifier)));
 }
 /// <summary>
 /// Get the individual words in the parameter name.  This way we can generate
 /// appropriate field/property names based on the user's preference.
 /// </summary>
 private List <string> GetParameterWordParts(IParameterSymbol parameter)
 => CreateWords(StringBreaker.BreakIntoWordParts(parameter.Name), parameter.Name);