/// <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)); }
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"); }
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()); }
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 <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);