コード例 #1
0
        static bool IsAvailableForType([NotNull] IType type, [NotNull] ITreeNode context)
        {
            if (type.IsGenericEnumerableOrDescendant() || type.IsGenericArray(context))
            {
                var elementType = CollectionTypeUtil.ElementTypeByCollectionType(type, context, false);
                if (elementType != null && elementType.Classify == TypeClassification.REFERENCE_TYPE)
                {
                    return(true);
                }
            }

            var resultType = type.GetTasklikeUnderlyingType(context);

            if (resultType != null && resultType.Classify == TypeClassification.REFERENCE_TYPE)
            {
                return(true);
            }

            if (type.IsLazy())
            {
                var typeElement = TypeElementUtil.GetTypeElementByClrName(PredefinedType.LAZY_FQN, context.GetPsiModule());
                var valueType   = type.GetGenericUnderlyingType(typeElement);
                if (valueType != null && valueType.Classify == TypeClassification.REFERENCE_TYPE)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #2
0
        protected override bool IsAvailableForType(IType type)
        {
            var context = Provider.SelectedElement;

            Debug.Assert(context != null);

            if ((type.IsCollectionLike() || type.IsGenericArray(context)) && !type.IsGenericIEnumerable() && !type.IsArray())
            {
                var elementType = CollectionTypeUtil.ElementTypeByCollectionType(type, context);

                if (elementType != null)
                {
                    if (elementType.Classify == TypeClassification.REFERENCE_TYPE)
                    {
                        isDictionary = false;
                        return(true);
                    }

                    if (type is IDeclaredType declaredType &&
                        (declaredType.GetKeyValueTypesForGenericDictionary() ?? Enumerable.Empty <JetBrains.Util.Pair <IType, IType> >()).Any(
                            pair => pair.Second.Classify == TypeClassification.REFERENCE_TYPE))
                    {
                        isDictionary = true;
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #3
0
        private static object GuessValueType(IExpression dictionary)
        {
            var declaredType = dictionary.Type() as IDeclaredType;

            if (declaredType == null)
            {
                return(null);
            }

            return(CollectionTypeUtil.GetKeyValueTypesForGenericDictionary(declaredType)?
                   .Select(x => x.Second)
                   .FirstOrDefault());
        }
コード例 #4
0
        /// <summary>
        /// Check for custom data type for input and output parameters specified for Lambda function.
        /// </summary>
        /// <param name="type">The <see cref="T:JetBrains.ReSharper.Psi.IType" /> to verify against custom user type</param>
        /// <returns>Whether type is a custom data type</returns>
        private static bool IsCustomDataType(IType type)
        {
            return(IsCustomDataType(type, new HashSet <IType>()));

            // "typesUnderProcess" store all types that are processing right now. Is used to avoid falling into infinitive recursion
            bool IsCustomDataType(IType typeToVerify, HashSet <IType> typesUnderProcess)
            {
                if (!typesUnderProcess.Add(typeToVerify))
                {
                    return(true);
                }

                if (ourLogger.IsTraceEnabled())
                {
                    ourLogger.Trace("Check is Custom Data for a type: {0}",
                                    typeToVerify.GetPresentableName(CSharpLanguage.Instance));
                }

                if (typeToVerify.IsVoid())
                {
                    return(false);
                }

                // Skip any primitive types, DateTime, and DateTimeOffset according to Newtonsoft.Json.Serialization logic.
                if (typeToVerify.IsSimplePredefined() || typeToVerify.IsDateTime() || typeToVerify.IsDateTimeOffset())
                {
                    return(true);
                }

                switch (typeToVerify)
                {
                case IArrayType arrayType:
                    return(IsCustomDataType(arrayType.ElementType, typesUnderProcess));

                case IDeclaredType declaredType:
                {
                    var predefinedType = declaredType.Module.GetPredefinedType();

                    var typeElement = declaredType.GetTypeElement();
                    if (ourLogger.IsTraceEnabled())
                    {
                        ourLogger.Trace("Check type element: {0}", typeElement?.GetClrName());
                    }
                    if (typeElement == null)
                    {
                        return(false);
                    }

                    // Define a substitution to verify generic types.
                    var substitution = declaredType.GetSubstitution();

                    // Check for dictionary types.
                    var genericDictionaryTypeElement = predefinedType.GenericIDictionary.GetTypeElement();
                    if (genericDictionaryTypeElement != null &&
                        typeElement.IsDescendantOf(genericDictionaryTypeElement))
                    {
                        var keyTypeParameter   = genericDictionaryTypeElement.TypeParameters[0];
                        var valueTypeParameter = genericDictionaryTypeElement.TypeParameters[1];

                        foreach (var ancestorSubstitution in typeElement.GetAncestorSubstitution(
                                     genericDictionaryTypeElement))
                        {
                            // Define a case when inner class override one TKey or TValue, e.g.
                            // class MyType<T> : IDictionary<int, T> {}
                            var effectiveSubstitution = ancestorSubstitution.Apply(substitution);

                            var keyType = effectiveSubstitution.Apply(keyTypeParameter);
                            if (!IsCustomDataType(keyType, typesUnderProcess))
                            {
                                return(false);
                            }

                            var valueType = effectiveSubstitution.Apply(valueTypeParameter);
                            if (!IsCustomDataType(valueType, typesUnderProcess))
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }

                    // Check for collection types.
                    var elementTypes =
                        CollectionTypeUtil.GetElementTypesForGenericType(
                            declaredType, predefinedType.GenericIEnumerable, 0)
                        ?? CollectionTypeUtil.GetElementTypesForGenericType(
                            declaredType, predefinedType.GenericIList, 0);

                    if (elementTypes != null)
                    {
                        return(elementTypes.All(elementType => IsCustomDataType(elementType, typesUnderProcess)));
                    }

                    // Check non-generic collection and map types
                    // assuming that value is of type Object and is always valid option.
                    if (declaredType.IsSubtypeOf(predefinedType.IEnumerable))
                    {
                        return(true);
                    }

                    // Check for POCO types
                    switch (typeElement)
                    {
                    case IClass classTypeElement:
                    {
                        var superClass = classTypeElement.GetBaseClassType();
                        if (!superClass.IsObject())
                        {
                            return(false);
                        }

                        return(classTypeElement.CanInstantiateWithPublicDefaultConstructor() &&
                               CheckMemberTypes(classTypeElement.GetMembers(), substitution, typesUnderProcess));
                    }

                    case IStruct structTypeElement:
                        return(CheckMemberTypes(structTypeElement.GetMembers(), substitution, typesUnderProcess));
                    }

                    break;
                }
                }

                return(false);
            }

            // Check all fields and properties inside a class or struct for a custom data type
            bool CheckMemberTypes(IEnumerable <ITypeMember> members, ISubstitution substitution, HashSet <IType> typesUnderProcess)
            {
                var typeMembers = members.AsArray();

                if (ourLogger.IsTraceEnabled())
                {
                    ourLogger.Trace("Verify members: {0}", string.Join(", ", typeMembers.Select(member => member.ShortName)));
                }

                foreach (var typeMember in typeMembers)
                {
                    if (typeMember.IsStatic)
                    {
                        continue;
                    }

                    switch (typeMember)
                    {
                    case IField field when field.IsField:
                    {
                        var fieldType = substitution.Apply(field.Type);
                        if (!IsCustomDataType(fieldType, typesUnderProcess))
                        {
                            return(false);
                        }
                        break;
                    }

                    case IProperty property when !property.IsDefault:
                    {
                        var propertyType = substitution.Apply(property.Type);
                        if (!IsCustomDataType(propertyType, typesUnderProcess))
                        {
                            return(false);
                        }
                        break;
                    }
                    }
                }

                return(true);
            }
        }
        private static bool CheckIfDestructureNeeded(ICSharpArgument argument)
        {
            bool CheckIfBaseToStringUsed(IType type)
            {
                if (type.IsObject())
                {
                    return(false);
                }

                if (type.IsPredefinedNumeric())
                {
                    return(false);
                }

                if (type.IsString())
                {
                    return(false);
                }

                if (type.IsGuid())
                {
                    return(false);
                }

                var classType = type.GetClassType();

                if (classType == null)
                {
                    return(false);
                }

                if (classType.Methods.Any(m => m.IsOverridesObjectToString()))
                {
                    return(false);
                }

                return(true);
            }

            // ReSharper disable once StyleCop.SA1305
            var iType = argument.GetExpressionType().ToIType();

            if (iType == null)
            {
                return(false);
            }

            if (iType.IsNullable())
            {
                var nullable = iType.GetNullableUnderlyingType();
                if (nullable == null)
                {
                    return(false);
                }

                return(CheckIfBaseToStringUsed(nullable));
            }

            if (iType is IDeclaredType declaredType)
            {
                if (Equals(declaredType.GetClrName(), GenericDictionaryFqn))
                {
                    var argumentType = declaredType.GetFirstGenericArgumentType();

                    return(argumentType != null && CheckIfBaseToStringUsed(argumentType));
                }

                var genericType = CollectionTypeUtil.GetElementTypesForGenericEnumerable(declaredType);
                if (genericType.Count == 1)
                {
                    return(CheckIfBaseToStringUsed(genericType.Single()));
                }
            }

            return(CheckIfBaseToStringUsed(iType));
        }
コード例 #6
0
        static void AnalyzeNotAllowedItemNotNull(
            [NotNull] IHighlightingConsumer consumer,
            [NotNull] IAttributesOwnerDeclaration attributesOwnerDeclaration)
        {
            var itemNotNullAttribute = attributesOwnerDeclaration.AttributesEnumerable.FirstOrDefault(
                attribute => attribute.AssertNotNull().GetAttributeInstance().GetAttributeType().GetClrName().ShortName ==
                ContainerElementNullnessProvider.ItemNotNullAttributeShortName);

            if (itemNotNullAttribute != null)
            {
                if (attributesOwnerDeclaration.OverridesInheritedMember())
                {
                    consumer.AddHighlighting(
                        new NotAllowedAnnotationHighlighting(
                            attributesOwnerDeclaration,
                            itemNotNullAttribute,
                            "Annotation is not allowed because the declared element overrides or implements the inherited member."));
                    return;
                }

                var type = TryGetTypeForIfCanBeAnnotatedWithItemNotNull(attributesOwnerDeclaration);
                if (type != null)
                {
                    if (type.IsGenericEnumerableOrDescendant() || type.IsGenericArray(attributesOwnerDeclaration))
                    {
                        var elementType = CollectionTypeUtil.ElementTypeByCollectionType(type, attributesOwnerDeclaration);
                        if (elementType != null)
                        {
                            if (elementType.Classify != TypeClassification.REFERENCE_TYPE)
                            {
                                consumer.AddHighlighting(
                                    new NotAllowedAnnotationHighlighting(
                                        attributesOwnerDeclaration,
                                        itemNotNullAttribute,
                                        "Annotation is not allowed because the declared element type is not a reference type."));
                            }
                        }
                        return;
                    }

                    var resultType = type.GetTasklikeUnderlyingType(attributesOwnerDeclaration);
                    if (resultType != null)
                    {
                        if (resultType.Classify != TypeClassification.REFERENCE_TYPE)
                        {
                            consumer.AddHighlighting(
                                new NotAllowedAnnotationHighlighting(
                                    attributesOwnerDeclaration,
                                    itemNotNullAttribute,
                                    "Annotation is not allowed because the declared task result type is not a reference type."));
                        }
                        return;
                    }

                    if (type.IsLazy())
                    {
                        var typeElement = TypeElementUtil.GetTypeElementByClrName(PredefinedType.LAZY_FQN, attributesOwnerDeclaration.GetPsiModule());
                        var valueType   = type.GetGenericUnderlyingType(typeElement);
                        if (valueType != null)
                        {
                            if (valueType.Classify != TypeClassification.REFERENCE_TYPE)
                            {
                                consumer.AddHighlighting(
                                    new NotAllowedAnnotationHighlighting(
                                        attributesOwnerDeclaration,
                                        itemNotNullAttribute,
                                        "Annotation is not allowed because the declared lazy value type is not a reference type."));
                            }
                        }
                        return;
                    }

                    consumer.AddHighlighting(
                        new NotAllowedAnnotationHighlighting(
                            attributesOwnerDeclaration,
                            itemNotNullAttribute,
                            string.Format(
                                "Annotation is not allowed because the declared element must be an {0}<T> (or its descendant), " +
                                "or a generic task-like type, or a {1}<T>.",
                                nameof(IEnumerable <int>),
                                nameof(Lazy <int>))));
                }
            }
        }