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