PsiType (final PsiField field, final Project project, final Map<String, PsiType> typeMap) { return CachedValuesManager.getCachedValue(field, () -> { final PsiType fieldType = field.getType(); final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType); final PsiClass fieldClass = resolveResult.getElement(); if (fieldClass == null) { final PsiType propertyType = eraseFreeTypeParameters(fieldType, field); return CachedValueProvider.Result.create(propertyType, PsiModificationTracker.MODIFICATION_COUNT); } PsiType substitute = null; for (String typeName : typeMap.keySet()) { if (InheritanceUtil.isInheritor(fieldType, typeName)) { substitute = typeMap.get(typeName); break; } } if (substitute == null) { if (!InheritanceUtil.isInheritor(fieldType, JavaFxCommonNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE)) { final PsiType propertyType = eraseFreeTypeParameters(fieldType, field); return CachedValueProvider.Result.create(propertyType, PsiModificationTracker.MODIFICATION_COUNT); } final PsiClass aClass = JavaPsiFacade.getInstance(project) .findClass(JavaFxCommonNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE, GlobalSearchScope.allScope(project)); LOG.assertTrue(aClass != null); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(aClass, fieldClass, resolveResult.getSubstitutor()); final PsiMethod[] values = aClass.findMethodsByName(JavaFxCommonNames.GET_VALUE, false); LOG.assertTrue(values.length == 1); substitute = substitutor.substitute(values[0].getReturnType()); } final PsiType propertyType = eraseFreeTypeParameters(substitute, field); return CachedValueProvider.Result.create(propertyType, PsiModificationTracker.MODIFICATION_COUNT); }); }