コード例 #1
0
        private static bool IsLazyEnumerable(InvocationExpressionSyntax invocation, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode> visited = null)
        {
            if (semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method &&
                method.ReturnType.IsAssignableTo(KnownSymbol.IEnumerable, semanticModel.Compilation) &&
                method.TrySingleDeclaration(cancellationToken, out MethodDeclarationSyntax methodDeclaration))
            {
                if (YieldStatementWalker.Any(methodDeclaration))
                {
                    return(true);
                }

                using (var walker = ReturnValueWalker.Borrow(methodDeclaration, ReturnValueSearch.TopLevel, semanticModel, cancellationToken))
                {
                    using (visited = visited.IncrementUsage())
                    {
                        foreach (var returnValue in walker)
                        {
                            if (returnValue is InvocationExpressionSyntax nestedInvocation &&
                                visited.Add(returnValue) &&
                                IsLazyEnumerable(nestedInvocation, semanticModel, cancellationToken, visited))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
コード例 #2
0
 private void Validate_IntersectWith(ISet <T> set, IEnumerable <T> enumerable)
 {
     if (set.Count == 0 || Enumerable.Count(enumerable) == 0)
     {
         set.IntersectWith(enumerable);
         Assert.Equal(0, set.Count);
     }
     else if (set == enumerable)
     {
         PooledSet <T> beforeOperation = new PooledSet <T>(set, GetIEqualityComparer());
         RegisterForDispose(beforeOperation);
         set.IntersectWith(enumerable);
         Assert.True(beforeOperation.SetEquals(set));
     }
     else
     {
         IEqualityComparer <T> comparer = GetIEqualityComparer();
         PooledSet <T>         expected = new PooledSet <T>(comparer);
         RegisterForDispose(expected);
         foreach (T value in set)
         {
             if (enumerable.Contains(value, comparer))
             {
                 expected.Add(value);
             }
         }
         set.IntersectWith(enumerable);
         Assert.Equal(expected.Count, set.Count);
         Assert.True(expected.SetEquals(set));
     }
 }
コード例 #3
0
        internal static AnalysisResult IsMatch(IMethodSymbol method, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <IMethodSymbol>?visited = null)
        {
            if (visited?.Add(method) == false)
            {
                return(AnalysisResult.No);
            }

            if (!IsPotentialMatch(method, semanticModel.Compilation))
            {
                return(AnalysisResult.No);
            }

            // not using known symbol here as both jetbrains & mvvm cross defines a NotifyPropertyChangedInvocatorAttribute
            if (method.GetAttributes().TryFirst(x => x.AttributeClass.Name == "NotifyPropertyChangedInvocatorAttribute", out _))
            {
                return(AnalysisResult.Yes);
            }

            var result = AnalysisResult.No;

            if (method.Parameters.TrySingle(out var parameter) &&
                method.TrySingleDeclaration(cancellationToken, out MethodDeclarationSyntax? declaration))
            {
                using var walker = InvocationWalker.Borrow(declaration);
                foreach (var invocation in walker.Invocations)
                {
                    if (invocation is { ArgumentList: { Arguments: { Count: 2 } oneArg } } &&
コード例 #4
0
        protected static PooledSet <int> CreatePooled(int size)
        {
            var rand = new Random(RAND_SEED);
            var set  = new PooledSet <int>(size);

            for (int i = 0; i < size; i++)
            {
                set.Add(rand.Next());
            }
            return(set);
        }
コード例 #5
0
 public static void UseSet(PooledSet <int> set)
 {
     using (set = set.IncrementUsage())
     {
         _ = set.Add(set.Count);
         foreach (var i in set)
         {
             var j = Id(i);
         }
     }
 }
        protected override IEnumerable NonGenericIEnumerableFactory(int count)
        {
            var set = new PooledSet <string>();

            RegisterForDispose(set);
            int seed = 12354;

            while (set.Count < count)
            {
                set.Add(CreateT(set, seed++));
            }
            return(set);
        }
コード例 #7
0
        private void Validate_SymmetricExceptWith(PooledSet <T> set, Span <T> span)
        {
            IEqualityComparer <T> comparer = set.Comparer;
            PooledSet <T>         expected = new PooledSet <T>(comparer);

            RegisterForDispose(expected);
            foreach (T element in span)
            {
                if (!set.Contains(element))
                {
                    expected.Add(element);
                }
            }
            foreach (T element in set)
            {
                if (!SpanContains(span, element, comparer))
                {
                    expected.Add(element);
                }
            }
            set.SymmetricExceptWith(span);
            Assert.Equal(expected.Count, set.Count);
            Assert.True(expected.SetEquals(set));
        }
コード例 #8
0
        /// <summary>
        /// Helper function to create an HashSet fulfilling the given specific parameters. The function will
        /// create an HashSet using the Comparer constructor and then add values
        /// to it until it is full. It will begin by adding the desired number of matching,
        /// followed by random (deterministic) elements until the desired count is reached.
        /// </summary>
        protected IEnumerable<T> CreateHashSet(IEnumerable<T> enumerableToMatchTo, int count, int numberOfMatchingElements)
        {
            var set = new PooledSet<T>(GetIEqualityComparer());
            RegisterForDispose(set);
            int seed = 528;
            List<T> match = null;

            // Add Matching elements
            if (enumerableToMatchTo != null)
            {
                match = enumerableToMatchTo.ToList();
                for (int i = 0; i < numberOfMatchingElements; i++)
                    set.Add(match[i]);
            }

            // Add elements to reach the desired count
            while (set.Count < count)
            {
                T toAdd = CreateT(seed++);
                while (set.Contains(toAdd) || (match != null && match.Contains(toAdd, GetIEqualityComparer()))) // Don't want any unexpectedly duplicate values
                    toAdd = CreateT(seed++);
                set.Add(toAdd);
            }

            // Validate that the Enumerable fits the guidelines as expected
            Debug.Assert(set.Count == count);
            if (match != null)
            {
                int actualMatchingCount = 0;
                foreach (T lookingFor in match)
                    actualMatchingCount += set.Contains(lookingFor) ? 1 : 0;
                Assert.Equal(numberOfMatchingElements, actualMatchingCount);
            }

            return set;
        }
コード例 #9
0
        public void ISet_Generic_SymmetricExceptWith_AfterRemovingElements(EnumerableType enumerableType, int setLength, int enumerableLength, int numberOfMatchingElements, int numberOfDuplicateElements)
        {
            ISet <T> set   = GenericISetFactory(setLength);
            T        value = CreateT(532);

            if (!set.Contains(value))
            {
                set.Add(value);
            }
            set.Remove(value);
            IEnumerable <T> enumerable = CreateEnumerable(enumerableType, set, enumerableLength, numberOfMatchingElements, numberOfDuplicateElements);

            Debug.Assert(enumerable != null);

            IEqualityComparer <T> comparer = GetIEqualityComparer();
            PooledSet <T>         expected = new PooledSet <T>(comparer);

            RegisterForDispose(expected);
            foreach (T element in enumerable)
            {
                if (!set.Contains(element, comparer))
                {
                    expected.Add(element);
                }
            }
            foreach (T element in set)
            {
                if (!enumerable.Contains(element, comparer))
                {
                    expected.Add(element);
                }
            }
            set.SymmetricExceptWith(enumerable);
            Assert.Equal(expected.Count, set.Count);
            Assert.True(expected.SetEquals(set));
        }
コード例 #10
0
        private void Validate_SymmetricExceptWith(ISet <T> set, IEnumerable <T> enumerable)
        {
            IEqualityComparer <T> comparer = GetIEqualityComparer();
            PooledSet <T>         expected = new PooledSet <T>(comparer);

            RegisterForDispose(expected);
            foreach (T element in enumerable)
            {
                if (!set.Contains(element, comparer))
                {
                    expected.Add(element);
                }
            }
            foreach (T element in set)
            {
                if (!enumerable.Contains(element, comparer))
                {
                    expected.Add(element);
                }
            }
            set.SymmetricExceptWith(enumerable);
            Assert.Equal(expected.Count, set.Count);
            Assert.True(expected.SetEquals(set));
        }
コード例 #11
0
        public void HashSet_Generic_RemoveWhere_NewObject(int setLength) // Regression Dev10_624201
        {
            object[]           array = new object[2];
            object             obj   = new object();
            PooledSet <object> set   = new PooledSet <object>();

            RegisterForDispose(set);

            set.Add(obj);
            set.Remove(obj);
            foreach (object o in set)
            {
            }
            set.CopyTo(array, 0, 2);
            set.RemoveWhere((element) => { return(false); });
        }
コード例 #12
0
        internal static bool IsAssignedToFieldOrProperty(ISymbol symbol, SyntaxNode scope, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <ISymbol> visited = null)
        {
            if (AssignmentExecutionWalker.FirstWith(symbol, scope, Scope.Instance, semanticModel, cancellationToken, out var assignment) &&
                semanticModel.TryGetSymbol(assignment.Left, cancellationToken, out ISymbol left))
            {
                if (left.IsEither <IParameterSymbol, ILocalSymbol>())
                {
                    using (visited = visited.IncrementUsage())
                    {
                        return(visited.Add(left) &&
                               IsAssignedToFieldOrProperty(left, scope, semanticModel, cancellationToken, visited));
                    }
                }

                return(left.IsEitherKind(SymbolKind.Field, SymbolKind.Property, SymbolKind.ArrayType));
            }

            return(false);
        }
コード例 #13
0
 private void Validate_IntersectWith(PooledSet <T> set, Span <T> span)
 {
     if (set.Count == 0 || span.Length == 0)
     {
         set.IntersectWith(span);
         Assert.Equal(0, set.Count);
     }
     else
     {
         IEqualityComparer <T> comparer = set.Comparer;
         PooledSet <T>         expected = new PooledSet <T>(comparer);
         RegisterForDispose(expected);
         foreach (T value in set)
         {
             if (SpanContains(span, value, comparer))
             {
                 expected.Add(value);
             }
         }
         set.IntersectWith(span);
         Assert.Equal(expected.Count, set.Count);
         Assert.True(expected.SetEquals(set));
     }
 }
コード例 #14
0
        private static Result CheckReturnValues(IParameterSymbol parameter, SyntaxNode memberAccess, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode> visited)
        {
            var result = Result.No;

            using (var returnWalker = ReturnValueWalker.Borrow(memberAccess, ReturnValueSearch.Recursive, semanticModel, cancellationToken))
            {
#pragma warning disable IDISP003
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003
                {
                    if (!visited.Add(memberAccess))
                    {
                        return(Result.Unknown);
                    }

                    foreach (var returnValue in returnWalker)
                    {
                        switch (CheckReturnValue(returnValue))
                        {
                        case Result.Unknown:
                            return(Result.Unknown);

                        case Result.Yes:
                            if (result == Result.No)
                            {
                                result = Result.Yes;
                            }

                            break;

                        case Result.AssumeYes:
                            result = Result.AssumeYes;
                            break;

                        case Result.No:
                            return(Result.No);

                        case Result.AssumeNo:
                            return(Result.AssumeNo);

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                    }
                }
            }

            return(result);

            Result CheckReturnValue(ExpressionSyntax returnValue)
            {
                if (returnValue is ObjectCreationExpressionSyntax nestedObjectCreation)
                {
                    if (nestedObjectCreation.TryFindArgument(parameter, out var nestedArgument))
                    {
                        return(IsArgumentDisposedByReturnValue(nestedArgument, semanticModel, cancellationToken, visited));
                    }

                    return(Result.No);
                }

                if (returnValue is InvocationExpressionSyntax nestedInvocation)
                {
                    if (nestedInvocation.TryFindArgument(parameter, out var nestedArgument))
                    {
                        return(IsArgumentDisposedByReturnValue(nestedArgument, semanticModel, cancellationToken, visited));
                    }

                    return(Result.No);
                }

                if (returnValue is MemberAccessExpressionSyntax nestedMemberAccess)
                {
                    return(IsArgumentDisposedByInvocationReturnValue(nestedMemberAccess, semanticModel, cancellationToken, visited));
                }

                return(Result.Unknown);
            }
        }
コード例 #15
0
        internal static bool IsValueValidForRegisteredType(ExpressionSyntax value, ITypeSymbol registeredType, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode>?visited = null)
        {
            switch (value)
            {
            case ConditionalExpressionSyntax conditional:
                return(IsValueValidForRegisteredType(conditional.WhenTrue, registeredType, semanticModel, cancellationToken, visited) &&
                       IsValueValidForRegisteredType(conditional.WhenFalse, registeredType, semanticModel, cancellationToken, visited));

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.CoalesceExpression):
                return(IsValueValidForRegisteredType(binary.Left, registeredType, semanticModel, cancellationToken, visited) &&
                       IsValueValidForRegisteredType(binary.Right, registeredType, semanticModel, cancellationToken, visited));
            }

            if (registeredType.TypeKind == TypeKind.Enum)
            {
                return(semanticModel.TryGetType(value, cancellationToken, out var valueType) &&
                       valueType.MetadataName == registeredType.MetadataName &&
                       Equals(valueType.ContainingType, registeredType.ContainingType) &&
                       NamespaceSymbolComparer.Equals(valueType.ContainingNamespace, registeredType.ContainingNamespace));
            }

            if (semanticModel.IsRepresentationPreservingConversion(value, registeredType))
            {
                return(true);
            }

            if (semanticModel.TryGetSymbol(value, cancellationToken, out var symbol))
            {
                if (symbol is IFieldSymbol field)
                {
                    if (field.TrySingleDeclaration(cancellationToken, out var fieldDeclaration))
                    {
                        if (fieldDeclaration.Declaration is { } variableDeclaration&&
                            variableDeclaration.Variables.TryLast(out var variable) &&
                            variable.Initializer is { } initializer&&
                            !IsValueValidForRegisteredType(initializer.Value, registeredType, semanticModel, cancellationToken, visited))
                        {
                            return(false);
                        }

                        return(IsAssignedValueOfRegisteredType(symbol, fieldDeclaration));
                    }

                    return(field.Type == KnownSymbols.Object);
                }

                if (symbol is IPropertySymbol property)
                {
                    if (property.TrySingleDeclaration(cancellationToken, out PropertyDeclarationSyntax? propertyDeclaration))
                    {
                        if (propertyDeclaration.Initializer is { } initializer&&
                            !IsValueValidForRegisteredType(initializer.Value, registeredType, semanticModel, cancellationToken, visited))
                        {
                            return(false);
                        }

                        if (property.SetMethod == null &&
                            property.GetMethod is { } getMethod)
                        {
                            return(IsReturnValueOfRegisteredType(getMethod));
                        }

                        return(IsAssignedValueOfRegisteredType(symbol, propertyDeclaration));
                    }

                    return(property.Type == KnownSymbols.Object);
                }

                if (symbol is IMethodSymbol method)
                {
                    return(IsReturnValueOfRegisteredType(method));
                }
            }

            return(false);

            bool IsAssignedValueOfRegisteredType(ISymbol memberSymbol, MemberDeclarationSyntax declaration)
            {
                if (declaration.TryFirstAncestor(out TypeDeclarationSyntax? typeDeclaration))
                {
                    using (var walker = AssignmentExecutionWalker.For(memberSymbol, typeDeclaration, SearchScope.Type, semanticModel, cancellationToken))
                    {
                        foreach (var assignment in walker.Assignments)
                        {
                            if (!IsValueValidForRegisteredType(assignment.Right, registeredType, semanticModel, cancellationToken, visited))
                            {
                                return(false);
                            }
                        }
                    }
                }

                return(true);
            }

            bool IsReturnValueOfRegisteredType(IMethodSymbol method)
            {
                if (method.TrySingleMethodDeclaration(cancellationToken, out var target))
                {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                    using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                    {
                        if (visited.Add(target))
                        {
                            using (var walker = ReturnValueWalker.Borrow(target))
                            {
                                foreach (var returnValue in walker.ReturnValues)
                                {
                                    if (!IsValueValidForRegisteredType(returnValue, registeredType, semanticModel, cancellationToken, visited))
                                    {
                                        return(false);
                                    }
                                }
                            }
                        }

                        return(true);
                    }
                }

                return(method.ReturnType == KnownSymbols.Object);
            }
        }
コード例 #16
0
        internal void EvaluateTrigger(RSTriggerId inTriggerId, ExecutionScope inScope)
        {
            if (!m_Entity.IsAlive())
            {
                return;
            }

            if (OnTrigger != null)
            {
                object arg = RSInterop.ToObject(inScope.Argument, inScope);
                OnTrigger.Invoke(inTriggerId, arg);
            }

            RSRuleData[] rules = m_Table?.Rules;
            int          ruleCount;

            if (rules == null || (ruleCount = rules.Length) <= 0)
            {
                return;
            }

            using (PooledSet <string> triggeredGroups = PooledSet <string> .Alloc())
            {
                for (int i = 0; i < ruleCount; ++i)
                {
                    RSRuleData rule = rules[i];
                    if (rule.TriggerId != inTriggerId)
                    {
                        continue;
                    }

                    if (m_States[i].HasFlag(RuleState.Disabled))
                    {
                        continue;
                    }

                    if (rule.DontInterrupt && m_Routines[i])
                    {
                        continue;
                    }

                    if (!inScope.EvaluateConditions(rule.Conditions, rule.ConditionSubset))
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(rule.RoutineGroup))
                    {
                        if (!triggeredGroups.Add(rule.RoutineGroup))
                        {
                            continue;
                        }

                        StopRuleGroup(rule.RoutineGroup);
                    }

                    if (rule.OnlyOnce)
                    {
                        m_States[i] |= RuleState.Disabled;
                    }

                    if (rule.Actions != null)
                    {
                        ExecutionScope scope = inScope;
                        scope.m_Environment.CloneScopeIfNecessary(scope, rule.Flags, out scope);

                        m_Routines[i].Replace(m_Entity.ProxyObject, scope.PerformActions(rule.Actions))
                        .ExecuteWhileDisabled().SetPhase(m_Entity.ExecutionPhase)
                        .TryManuallyUpdate(0);
                    }
                }
            }
        }
コード例 #17
0
        private static bool TryGet(ExpressionSyntax expression, SyntaxNodeAnalysisContext context, PooledSet <ExpressionSyntax> visited, out ITypeSymbol result, out ExpressionSyntax source)
        {
            switch (expression)
            {
            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "ReturnType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetMethod(invocation, context, out var reflectedMember, out _, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IMethodSymbol method:
                source = memberAccess;
                result = method.ReturnType;
                return(true);

            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "FieldType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetField(invocation, context, out var reflectedMember, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IFieldSymbol field:
                source = memberAccess;
                result = field.Type;
                return(true);

            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "PropertyType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetProperty(invocation, context, out var reflectedMember, out _, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IPropertySymbol field:
                source = memberAccess;
                result = field.Type;
                return(true);

            case TypeOfExpressionSyntax typeOf:
                source = typeOf;
                return(context.SemanticModel.TryGetType(typeOf.Type, context.CancellationToken, out result));

            case InvocationExpressionSyntax invocation when invocation.ArgumentList is ArgumentListSyntax args &&
                args.Arguments.Count == 0 &&
                invocation.TryGetMethodName(out var name) &&
                name == "GetType":
                switch (invocation.Expression)
                {
                case MemberAccessExpressionSyntax typeAccess:
                    source = invocation;
                    if (context.SemanticModel.TryGetType(typeAccess.Expression, context.CancellationToken, out result))
                    {
                        if (result is INamedTypeSymbol namedType &&
                            namedType.ConstructedFrom?.SpecialType == SpecialType.System_Nullable_T)
                        {
                            result = namedType.TypeArguments[0];
                        }

                        return(true);
                    }

                    return(false);

                case IdentifierNameSyntax _ when expression.TryFirstAncestor(out TypeDeclarationSyntax containingType):
                    source = invocation;

                    return(context.SemanticModel.TryGetSymbol(containingType, context.CancellationToken, out result));

                case MemberBindingExpressionSyntax memberBinding when memberBinding.Parent?.Parent is ConditionalAccessExpressionSyntax conditionalAccess:
                    source = invocation;
                    return(context.SemanticModel.TryGetType(conditionalAccess.Expression, context.CancellationToken, out result));
                }

                break;

            case InvocationExpressionSyntax candidate when TryMatchTypeGetType(candidate, context, out var typeName, out var ignoreCase):
                source = candidate;

                result = context.Compilation.GetTypeByMetadataName(typeName, ignoreCase.Value);
                return(result != null);

            case InvocationExpressionSyntax candidate when TryMatchAssemblyGetType(candidate, context, out var typeName, out var ignoreCase):
                source = candidate;

                result = Assembly.TryGet(candidate.Expression, context, out var assembly)
                        ? assembly.GetTypeByMetadataName(typeName, ignoreCase.Value)
                        : null;
                return(result != null);

            case InvocationExpressionSyntax invocation when invocation.TryGetTarget(KnownSymbol.Type.GetGenericTypeDefinition, context.SemanticModel, context.CancellationToken, out _) &&
                invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                TryGet(memberAccess.Expression, context, visited, out var definingType, out _) &&
                definingType is INamedTypeSymbol namedType:
                source = invocation;

                result = namedType.ConstructedFrom;
                return(true);

            case InvocationExpressionSyntax invocation when GetX.TryMatchGetNestedType(invocation, context, out var reflectedMember, out _, out _):
                source = invocation;

                result = reflectedMember.Symbol as ITypeSymbol;
                return(result != null && reflectedMember.Match == FilterMatch.Single);

            case InvocationExpressionSyntax invocation when invocation.TryGetTarget(KnownSymbol.Type.MakeGenericType, context.SemanticModel, context.CancellationToken, out _) &&
                invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                TypeArguments.TryCreate(invocation, context, out var typeArguments) &&
                typeArguments.TryGetArgumentsTypes(context, out var types):
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    if (visited.Add(invocation) &&
                        TryGet(memberAccess.Expression, context, visited, out var definition, out _) &&
                        definition is INamedTypeSymbol namedType)
                    {
                        source = invocation;
                        result = namedType.Construct(types);
                        return(result != null);
                    }
                }

                break;

            case ConditionalAccessExpressionSyntax conditionalAccess:
                source = conditionalAccess;
                return(TryGet(conditionalAccess.WhenNotNull, context, out result, out _));
            }

            if (expression.IsEither(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) &&
                context.SemanticModel.TryGetSymbol(expression, context.CancellationToken, out ISymbol local))
            {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    source = null;
                    result = null;
                    return(AssignedValue.TryGetSingle(local, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                           visited.Add(assignedValue) &&
                           TryGet(assignedValue, context, visited, out result, out source));
                }
            }

            source = null;
            result = null;
            return(false);
        }
コード例 #18
0
        private static bool IsDefaultValueOfRegisteredType(ExpressionSyntax defaultValue, ITypeSymbol registeredType, SyntaxNodeAnalysisContext context, PooledSet <SyntaxNode> visited = null)
        {
            switch (defaultValue)
            {
            case ConditionalExpressionSyntax conditional:
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    return(visited.Add(defaultValue) &&
                           IsDefaultValueOfRegisteredType(conditional.WhenTrue, registeredType, context, visited) &&
                           IsDefaultValueOfRegisteredType(conditional.WhenFalse, registeredType, context, visited));
                }

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.CoalesceExpression):
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    return(visited.Add(defaultValue) &&
                           IsDefaultValueOfRegisteredType(binary.Left, registeredType, context, visited) &&
                           IsDefaultValueOfRegisteredType(binary.Right, registeredType, context, visited));
                }
            }

            if (context.SemanticModel.IsRepresentationPreservingConversion(defaultValue, registeredType, context.CancellationToken))
            {
                return(true);
            }

            if (context.SemanticModel.TryGetSymbol(defaultValue, context.CancellationToken, out ISymbol symbol))
            {
                if (symbol is IFieldSymbol field)
                {
                    if (field.TrySingleDeclaration(context.CancellationToken, out var fieldDeclaration))
                    {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                        using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                        {
                            if (fieldDeclaration.Declaration is VariableDeclarationSyntax variableDeclaration &&
                                variableDeclaration.Variables.TryLast(out var variable) &&
                                variable.Initializer is EqualsValueClauseSyntax initializer)
                            {
                                return(visited.Add(initializer.Value) &&
                                       IsDefaultValueOfRegisteredType(initializer.Value, registeredType, context, visited));
                            }

                            return(fieldDeclaration.TryFirstAncestor <TypeDeclarationSyntax>(out var typeDeclaration) &&
                                   AssignmentExecutionWalker.SingleFor(symbol, typeDeclaration, Scope.Instance, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                                   visited.Add(assignedValue) &&
                                   IsDefaultValueOfRegisteredType(assignedValue, registeredType, context, visited));
                        }
                    }

                    return(field.Type == KnownSymbol.Object);
                }

                if (symbol is IPropertySymbol property)
                {
                    if (property.TrySingleDeclaration(context.CancellationToken, out PropertyDeclarationSyntax propertyDeclaration))
                    {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                        using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                        {
                            if (propertyDeclaration.Initializer is EqualsValueClauseSyntax initializer)
                            {
                                return(visited.Add(initializer.Value) &&
                                       IsDefaultValueOfRegisteredType(initializer.Value, registeredType, context, visited));
                            }

                            if (property.SetMethod == null &&
                                property.GetMethod is IMethodSymbol getMethod)
                            {
                                return(IsReturnValueOfRegisteredType(getMethod, visited));
                            }

                            return(propertyDeclaration.TryFirstAncestor <TypeDeclarationSyntax>(out var typeDeclaration) &&
                                   AssignmentExecutionWalker.SingleFor(symbol, typeDeclaration, Scope.Instance, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                                   visited.Add(assignedValue) &&
                                   IsDefaultValueOfRegisteredType(assignedValue, registeredType, context, visited));
                        }
                    }

                    return(property.Type == KnownSymbol.Object);
                }

                if (symbol is IMethodSymbol method)
                {
                    return(IsReturnValueOfRegisteredType(method, visited));
                }
            }

            return(false);

            bool IsReturnValueOfRegisteredType(IMethodSymbol method, PooledSet <SyntaxNode> v)
            {
                if (method.TrySingleMethodDeclaration(context.CancellationToken, out var target))
                {
                    using (var walker = ReturnValueWalker.Borrow(target))
                    {
                        foreach (var returnValue in walker.ReturnValues)
                        {
                            if (!IsDefaultValueOfRegisteredType(returnValue, registeredType, context, v))
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }
                }

                return(method.ReturnType == KnownSymbol.Object);
            }
        }