コード例 #1
0
 internal SyntaxNode CreateOrdinalMemberAccess(SyntaxGenerator syntaxFactoryService, SemanticModel model)
 {
     var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation);
     return syntaxFactoryService.MemberAccessExpression(
         syntaxFactoryService.TypeExpression(stringComparisonType),
         syntaxFactoryService.IdentifierName(CA1309DiagnosticAnalyzer.OrdinalText));
 }
        private static IList<SyntaxNode> CreateGetHashCodeMethodStatements(
            SyntaxGenerator factory,
            Compilation compilation,
            INamedTypeSymbol containingType,
            IList<ISymbol> members,
            CancellationToken cancellationToken)
        {
            const string HashCodeName = "hashCode";

            // -1521134295
            var permuteValue = factory.NegateExpression(
                factory.LiteralExpression(1521134295));

            var statements = new List<SyntaxNode>();

            var hashCodeNameExpression = factory.IdentifierName(HashCodeName);

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

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

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

            return statements;
        }
コード例 #3
0
        private IFieldSymbol GetExplicitlyAssignedField(IFieldSymbol originalField, SyntaxGenerator syntaxFactoryService)
        {
            var originalInitializer = GetFieldInitializer(originalField);
            if (originalInitializer != null || !originalField.HasConstantValue)
            {
                return originalField;
            }

            var constantValueExpression = syntaxFactoryService.LiteralExpression(originalField.ConstantValue);
            var newInitializer = CreateConstantValueInitializer(constantValueExpression);

            return CodeGenerationSymbolFactory.CreateFieldSymbol(originalField.GetAttributes(), originalField.DeclaredAccessibility, originalField.GetSymbolModifiers(),
                originalField.Type, originalField.Name, originalField.HasConstantValue, originalField.ConstantValue, newInitializer);
        }
コード例 #4
0
        public static SyntaxNode GenerateThrowStatement(
            SyntaxGenerator factory,
            SemanticDocument document,
            string exceptionMetadataName,
            CancellationToken cancellationToken)
        {
            var compilation = document.SemanticModel.Compilation;
            var exceptionType = compilation.GetTypeByMetadataName(exceptionMetadataName);

            // If we can't find the Exception, we obviously can't generate anything.
            if (exceptionType == null)
            {
                return null;
            }

            var exceptionCreationExpression = factory.ObjectCreationExpression(
                exceptionType,
                SpecializedCollections.EmptyList<SyntaxNode>());

            return factory.ThrowStatement(exceptionCreationExpression);
        }
コード例 #5
0
        internal SyntaxNode CreateEqualsExpression(SyntaxGenerator syntaxFactoryService, SemanticModel model, SyntaxNode operand1, SyntaxNode operand2, bool isEquals)
        {
            var stringType = model.Compilation.GetSpecialType(SpecialType.System_String);
            var memberAccess = syntaxFactoryService.MemberAccessExpression(
                        syntaxFactoryService.TypeExpression(stringType),
                        syntaxFactoryService.IdentifierName(CA1309DiagnosticAnalyzer.EqualsMethodName));
            var ordinal = CreateOrdinalMemberAccess(syntaxFactoryService, model);
            var invocation = syntaxFactoryService.InvocationExpression(
                memberAccess,
                operand1,
                operand2.WithTrailingTrivia(),
                ordinal)
                .WithAdditionalAnnotations(Formatter.Annotation);
            if (!isEquals)
            {
                invocation = syntaxFactoryService.LogicalNotExpression(invocation);
            }

            invocation = invocation.WithTrailingTrivia(operand2.GetTrailingTrivia());

            return invocation;
        }
コード例 #6
0
        protected IMethodSymbol CreateGet(string originalFieldName, IFieldSymbol field, SyntaxGenerator factory)
        {
            var body = factory.ReturnStatement(
                factory.IdentifierName(originalFieldName));

            return CodeGenerationSymbolFactory.CreateAccessorSymbol(SpecializedCollections.EmptyList<AttributeData>(),
                Accessibility.NotApplicable,
                new[] { body }.ToList());
        }
コード例 #7
0
        protected IMethodSymbol CreateSet(string originalFieldName, IFieldSymbol field, SyntaxGenerator factory)
        {
            var assigned = !field.IsStatic
                ? factory.MemberAccessExpression(
                    factory.ThisExpression(),
                    factory.IdentifierName(originalFieldName))
                : factory.IdentifierName(originalFieldName);

            var body = factory.ExpressionStatement(
                factory.AssignmentStatement(
                    assigned.WithAdditionalAnnotations(Simplifier.Annotation),
                factory.IdentifierName("value")));

            return CodeGenerationSymbolFactory.CreateAccessorSymbol(SpecializedCollections.EmptyList<AttributeData>(),
                Accessibility.NotApplicable,
                new[] { body }.ToList());
        }
コード例 #8
0
 internal SyntaxNode CreateCharSetArgument(SyntaxGenerator syntaxFactoryService, INamedTypeSymbol charSetType)
 {
     return syntaxFactoryService.MemberAccessExpression(
         syntaxFactoryService.TypeExpression(charSetType), syntaxFactoryService.IdentifierName(UnicodeText));
 }
コード例 #9
0
 internal SyntaxNode CreateMarshalAsArgument(SyntaxGenerator syntaxFactoryService, INamedTypeSymbol unmanagedType)
 {
     return syntaxFactoryService.MemberAccessExpression(
         syntaxFactoryService.TypeExpression(unmanagedType), syntaxFactoryService.IdentifierName(LPWStrText));
 }
コード例 #10
0
 private SyntaxNode GenerateName(SyntaxGenerator factory, bool isGenericType)
 {
     return isGenericType 
         ? factory.GenericName(State.ClassOrStructType.Name, State.ClassOrStructType.TypeArguments) 
         : factory.IdentifierName(State.ClassOrStructType.Name);
 }
コード例 #11
0
            private SyntaxNode CreateThroughExpression(SyntaxGenerator factory)
            {
                var through = ThroughMember.IsStatic
                        ? GenerateName(factory, State.ClassOrStructType.IsGenericType)
                        : factory.ThisExpression();

                through = factory.MemberAccessExpression(
                    through, factory.IdentifierName(ThroughMember.Name));

                var throughMemberType = ThroughMember.GetMemberType();
                if ((State.InterfaceTypes != null) && (throughMemberType != null))
                {
                    // In the case of 'implement interface through field / property' , we need to know what
                    // interface we are implementing so that we can insert casts to this interface on every
                    // usage of the field in the generated code. Without these casts we would end up generating
                    // code that fails compilation in certain situations.
                    // 
                    // For example consider the following code.
                    //      class C : IReadOnlyList<int> { int[] field; }
                    // When applying the 'implement interface through field' code fix in the above example,
                    // we need to generate the following code to implement the Count property on IReadOnlyList<int>
                    //      class C : IReadOnlyList<int> { int[] field; int Count { get { ((IReadOnlyList<int>)field).Count; } ...}
                    // as opposed to the following code which will fail to compile (because the array field
                    // doesn't have a property named .Count) -
                    //      class C : IReadOnlyList<int> { int[] field; int Count { get { field.Count; } ...}
                    //
                    // The 'InterfaceTypes' property on the state object always contains only one item
                    // in the case of C# i.e. it will contain exactly the interface we are trying to implement.
                    // This is also the case most of the time in the case of VB, except in certain error conditions
                    // (recursive / circular cases) where the span of the squiggle for the corresponding 
                    // diagnostic (BC30149) changes and 'InterfaceTypes' ends up including all interfaces
                    // in the Implements clause. For the purposes of inserting the above cast, we ignore the
                    // uncommon case and optimize for the common one - in other words, we only apply the cast
                    // in cases where we can unambiguously figure out which interface we are trying to implement.
                    var interfaceBeingImplemented = State.InterfaceTypes.SingleOrDefault();
                    if ((interfaceBeingImplemented != null) && (!throughMemberType.Equals(interfaceBeingImplemented)))
                    {
                        through = factory.CastExpression(interfaceBeingImplemented,
                            through.WithAdditionalAnnotations(Simplifier.Annotation));

                        var facts = this.Document.GetLanguageService<ISyntaxFactsService>();
                        through = facts.Parenthesize(through);
                    }
                }

                return through.WithAdditionalAnnotations(Simplifier.Annotation);
            }
        private static IList<SyntaxNode> CreateEqualsMethodStatements(
            SyntaxGenerator 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.IdentifierName(localName);

            var objNameExpression = factory.IdentifierName(ObjName);

            var expressions = new List<SyntaxNode>();

            if (containingType.IsValueType)
            {
#if false
                if (!(obj is MyType))
                {
                    return false;
                }
#endif
                var ifStatement = factory.IfStatement(
                    factory.LogicalNotExpression(
                        factory.IsTypeExpression(
                            objNameExpression,
                            containingType)),
                    new[] { factory.ReturnStatement(factory.FalseLiteralExpression()) });

#if false
                var myType = (MyType)obj;
#endif
                var localDeclaration = factory.LocalDeclarationStatement(localName, factory.CastExpression(containingType, objNameExpression));

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

                statements.Add(localDeclaration);

#if false
                myType != null
#endif
                expressions.Add(factory.ReferenceNotEqualsExpression(localNameExpression, factory.NullLiteralExpression()));
                if (HasExistingBaseEqualsMethod(containingType, cancellationToken))
                {
#if false
                    base.Equals(obj)
#endif
                    expressions.Add(factory.InvocationExpression(
                        factory.MemberAccessExpression(
                            factory.BaseExpression(),
                            factory.IdentifierName(EqualsName)),
                        objNameExpression));
                }
            }

            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);

#if false
                EqualityComparer<SType>.Default.Equals(this.S1, myType.S1)
#endif
                var expression =
                    factory.InvocationExpression(
                        factory.MemberAccessExpression(
                            GetDefaultEqualityComparer(factory, compilation, member),
                            factory.IdentifierName(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.ReturnStatement(
                expressions.Aggregate(factory.LogicalAndExpression)));

            return statements;
        }
 private static SyntaxNode GetDefaultEqualityComparer(
     SyntaxGenerator factory,
     Compilation compilation,
     ISymbol member)
 {
     var equalityComparerType = compilation.EqualityComparerOfTType();
     var constructedType = equalityComparerType.Construct(GetType(compilation, member));
     return factory.MemberAccessExpression(
         factory.TypeExpression(constructedType),
         factory.IdentifierName(DefaultName));
 }
        private static SyntaxNode ComputeHashValue(
            SyntaxGenerator factory,
            Compilation compilation,
            ISymbol member)
        {
            var getHashCodeNameExpression = factory.IdentifierName(GetHashCodeName);
            var thisSymbol = factory.MemberAccessExpression(factory.ThisExpression(),
                factory.IdentifierName(member.Name)).WithAdditionalAnnotations(Simplification.Simplifier.Annotation);

#if false
            EqualityComparer<SType>.Default.GetHashCode(this.S1)
#endif

            return factory.InvocationExpression(
                factory.MemberAccessExpression(
                    GetDefaultEqualityComparer(factory, compilation, member),
                    getHashCodeNameExpression),
                thisSymbol);
        }
コード例 #15
0
        private IList<ISymbol> GetNewFieldsForRuleNameNoZeroValue(INamedTypeSymbol enumType, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Add a member to '{0}' that has a value of zero with a suggested name of 'None'.
            // Fix: Add a zero-valued member 'None' to enum.

            var newFields = new List<ISymbol>();
            var constantValueExpression = syntaxFactoryService.LiteralExpression(0);
            var newInitializer = CreateConstantValueInitializer(constantValueExpression);
            var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(SpecializedCollections.EmptyList<AttributeData>(), Accessibility.Public,
                    default(SymbolModifiers), enumType.EnumUnderlyingType, "None", true, 0, newInitializer);
            newFields.Add(newField);

            foreach (var member in enumType.GetMembers())
            {
                if (!CA1008DiagnosticAnalyzer.IsMemberNamedNone(member))
                {
                    newFields.Add(member);
                }
            }

            return newFields;
        }
コード例 #16
0
        private IList<ISymbol> GetNewFieldsForRuleNameMultipleZero(INamedTypeSymbol enumType, IEnumerable<IFieldSymbol> zeroValuedFields, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Remove all members that have the value zero from '{0}' except for one member that is named 'None'.
            // Fix: Remove all members that have the value zero except for one member that is named 'None'.

            bool needsNewZeroValuedNoneField = true;
            var set = zeroValuedFields.ToSet();

            bool makeNextFieldExplicit = false;
            var newFields = new List<ISymbol>();
            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                var isZeroValued = set.Contains(field);
                var isZeroValuedNamedNone = isZeroValued && CA1008DiagnosticAnalyzer.IsMemberNamedNone(field);

                if (!isZeroValued || isZeroValuedNamedNone)
                {
                    var newField = field;
                    if (makeNextFieldExplicit)
                    {
                        newField = GetExplicitlyAssignedField(field, syntaxFactoryService);
                        makeNextFieldExplicit = false;
                    }

                    newFields.Add(newField);

                    if (isZeroValuedNamedNone)
                    {
                        needsNewZeroValuedNoneField = false;
                    }
                }
                else
                {
                    makeNextFieldExplicit = true;
                }
            }

            if (needsNewZeroValuedNoneField)
            {
                var firstZeroValuedField = zeroValuedFields.First();
                var constantValueExpression = syntaxFactoryService.LiteralExpression(firstZeroValuedField.ConstantValue);
                var newInitializer = CreateConstantValueInitializer(constantValueExpression);
                var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(firstZeroValuedField.GetAttributes(), firstZeroValuedField.DeclaredAccessibility, firstZeroValuedField.GetSymbolModifiers(),
                    firstZeroValuedField.Type, "None", firstZeroValuedField.HasConstantValue, firstZeroValuedField.ConstantValue, newInitializer);
                newFields.Insert(0, newField);
            }

            return newFields;
        }