DfaValue (DfaCallArguments arguments, DfaMemoryState state, DfaValueFactory factory, PsiMethod method) { DfType result = DfType.TOP; DfaValue collection = arguments.myQualifier; DfaValue collectionSize = COLLECTION_SIZE.createValue(factory, collection); LongRangeSet collectionSizeRange = DfIntType.extractRange(state.getDfType(collectionSize)); DfaValue finalSize = collectionSize; if (arguments.myArguments.length == 1) { DfaValue array = arguments.myArguments[0]; DfType arrType = state.getDfType(array); TypeConstraint constraint = TypeConstraint.fromDfType(arrType); if (constraint.isExact()) { result = constraint.asDfType(); } // Array size is max of collection size and argument array size DfaValue arrayLength = ARRAY_LENGTH.createValue(factory, array); if (!state.areEqual(arrayLength, collectionSize)) { LongRangeSet arraySizeRange = DfIntType.extractRange(state.getDfType(arrayLength)); LongRangeSet biggerArrays = collectionSizeRange.fromRelation(RelationType.GT).meet(arraySizeRange); LongRangeSet biggerCollections = arraySizeRange.fromRelation(RelationType.GE).meet(collectionSizeRange); if (!biggerArrays.isEmpty()) { finalSize = factory.fromDfType(intRange(biggerArrays.join(biggerCollections))); } } } else if (arguments.myArguments.length == 0) { PsiType type = method.getReturnType(); if (type instanceof PsiArrayType) { // Assume that collection.toArray() always returns Object[] exactly. // it may be different (e.g. Arrays.asList().toArray() returned more precise type in older JDK) // but it violates the spec. result = TypeConstraints.exact(type).asDfType(); } } return factory.getWrapperFactory().createWrapper(result.meet(NOT_NULL_OBJECT), ARRAY_LENGTH, finalSize); }