Partially fix the issue #1743 ConditionalExpr resolves to wrong type
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java
index ae77968..5958f2a 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java
@@ -89,6 +89,7 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.github.javaparser.utils.Log;
 import com.github.javaparser.utils.Pair;
@@ -194,10 +195,149 @@
         return new ReferenceTypeImpl(new ReflectionClassDeclaration(Class.class, typeSolver), ImmutableList.of(jssType), typeSolver);
     }
 
+    /*
+     * The conditional operator has three operand expressions. ? appears between the first and second expressions, and
+     * : appears between the second and third expressions.
+     * There are three kinds of conditional expressions, classified according to the second and third operand
+     * expressions: boolean conditional expressions, numeric conditional expressions, and reference conditional
+     * expressions.
+     * The classification rules are as follows:
+     * 1/ If both the second and the third operand expressions are boolean expressions, the conditional expression is a
+     * boolean conditional expression.
+     * 2/ If both the second and the third operand expressions are numeric expressions, the conditional expression is a
+     * numeric conditional expression.
+     * 3/ Otherwise, the conditional expression is a reference conditional expression
+     */
     @Override
     public ResolvedType visit(ConditionalExpr node, Boolean solveLambdas) {
+        ResolvedType thenExpr = node.getThenExpr().accept(this, solveLambdas);
+        ResolvedType elseExpr = node.getElseExpr().accept(this, solveLambdas);
+        
+        // manage null expression
+        if ( thenExpr.isNull()) {
+            return  elseExpr;
+        }
+        if ( elseExpr.isNull()) {
+            return  thenExpr;
+        }
+        /*
+         * Boolean conditional expressions are standalone expressions
+         * The type of a boolean conditional expression is determined as follows:
+         * If the second and third operands are both of type Boolean, the conditional expression has type Boolean.
+         * Otherwise, the conditional expression has type boolean.
+         */
+        if ( thenExpr.isAssignableBy(ResolvedPrimitiveType.BOOLEAN) 
+                && elseExpr.isAssignableBy(ResolvedPrimitiveType.BOOLEAN)) {
+            if (thenExpr.isReferenceType() && elseExpr.isReferenceType()) {
+                return thenExpr.asReferenceType();
+            }
+            return thenExpr.isPrimitive() ? thenExpr : elseExpr;
+        }
+        
+        /*
+         * Numeric conditional expressions are standalone expressions (§15.2).
+         * The type of a numeric conditional expression is determined as follows:
+         * If the second and third operands have the same type, then that is the type of the conditional expression.
+         * If one of the second and third operands is of primitive type T, and the type of the other is the result of
+         * applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
+         * If one of the operands is of type byte or Byte and the other is of type short or Short, then the type of the
+         * conditional expression is short.
+         * If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant
+         * expression (§15.28) of type int whose value is representable in type T, then the type of the conditional
+         * expression is T.
+         * If one of the operands is of type T, where T is Byte, Short, or Character, and the other operand is a
+         * constant expression of type int whose value is representable in the type U which is the result of applying
+         * unboxing conversion to T, then the type of the conditional expression is U.
+         * Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the
+         * conditional expression is the promoted type of the second and third operands.
+         */
+        if (TypeHelper.isNumericType(thenExpr) && TypeHelper.isNumericType(elseExpr)) {
+            ResolvedPrimitiveType[] resolvedPrimitiveTypeSubList = new ResolvedPrimitiveType[] {ResolvedPrimitiveType.BYTE, ResolvedPrimitiveType.SHORT, ResolvedPrimitiveType.CHAR};
+            /*
+             *  If the second and third operands have the same type, then that is the type of the conditional expression.
+             */
+            String qnameTypeThenExpr = thenExpr.isPrimitive() ? thenExpr.asPrimitive().describe()
+                    : thenExpr.asReferenceType().describe();
+            String qnameTypeElseExpr = elseExpr.isPrimitive() ? elseExpr.asPrimitive().describe()
+                    : elseExpr.asReferenceType().describe();
+            if (qnameTypeThenExpr.equals(qnameTypeElseExpr)) {
+                return thenExpr;
+            }
+            /*
+             * If one of the second and third operands is of primitive type T, and the type of the other is the result of
+             * applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
+             */
+            else if ((thenExpr.isPrimitive() && elseExpr.isReferenceType()
+                    && isCompatible(elseExpr.asReferenceType(), thenExpr.asPrimitive()))) {
+                return thenExpr;
+            } else if ((elseExpr.isPrimitive() && thenExpr.isReferenceType()
+                    && isCompatible(thenExpr.asReferenceType(), elseExpr.asPrimitive()))) {
+                return elseExpr;
+            }
+            /*
+             * If one of the operands is of type byte or Byte and the other is of type short or Short, then the type of the
+             * conditional expression is short.
+             */
+            else if ((isCompatible(thenExpr, ResolvedPrimitiveType.BYTE) && isCompatible(elseExpr, ResolvedPrimitiveType.SHORT))
+                    || (isCompatible(elseExpr, ResolvedPrimitiveType.BYTE) && isCompatible(thenExpr, ResolvedPrimitiveType.SHORT))) {
+                return ResolvedPrimitiveType.SHORT;
+            }
+            /*
+             *  If one of the operands is of type T where T is byte, short, or char, and the
+             *  other operand is a constant expression (§15.28) of type int whose value is
+             *  representable in type T, then the type of the conditional expression is T
+             *  How can we know if the constant expression of type int is representable in type T ?
+             *  "The constant expression of type int is representable in type T" is a runtime decision!
+             */
+            else if (thenExpr.isPrimitive() && elseExpr.isPrimitive()) {
+                if (((ResolvedPrimitiveType)thenExpr).in(resolvedPrimitiveTypeSubList)
+                    && ((ResolvedPrimitiveType)elseExpr).equals(ResolvedPrimitiveType.INT)) {
+                    return thenExpr;
+                } else if (((ResolvedPrimitiveType)elseExpr).in(resolvedPrimitiveTypeSubList)
+                    && ((ResolvedPrimitiveType)thenExpr).equals(ResolvedPrimitiveType.INT)) {
+                    return elseExpr;
+                }
+            }
+             /*  If one of the operands is of type T, where T is Byte, Short, or Character,
+             * and the other operand is a constant expression of type int whose value is
+             * representable in the type U which is the result of applying unboxing
+             * conversion to T, then the type of the conditional expression is U.
+             * A priori this is a runtime decision!
+             */
+            else if (thenExpr.isReference() && elseExpr.isPrimitive()
+                    && TypeHelper.toUnboxedType(thenExpr.asReferenceType()).in(resolvedPrimitiveTypeSubList)
+                    && ((ResolvedPrimitiveType)elseExpr).equals(ResolvedPrimitiveType.INT)) {
+                return TypeHelper.toUnboxedType(thenExpr.asReferenceType());
+            } else if (elseExpr.isReference() && thenExpr.isPrimitive()
+                    && TypeHelper.toUnboxedType(elseExpr.asReferenceType()).in(resolvedPrimitiveTypeSubList)
+                    && ((ResolvedPrimitiveType)thenExpr).equals(ResolvedPrimitiveType.INT)) {
+                return TypeHelper.toUnboxedType(elseExpr.asReferenceType());
+            }
+             
+            /* Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types,
+             * and the type of the conditional expression is the promoted type of the second
+             * and third operands.
+             */
+            ResolvedPrimitiveType PrimitiveThenExpr = thenExpr.isPrimitive() ? thenExpr.asPrimitive()
+                    : TypeHelper.toUnboxedType(thenExpr.asReferenceType());
+            ResolvedPrimitiveType PrimitiveElseExpr = elseExpr.isPrimitive() ? elseExpr.asPrimitive()
+                    : TypeHelper.toUnboxedType(elseExpr.asReferenceType());
+            return PrimitiveThenExpr.bnp(PrimitiveElseExpr);
+        }
+        
+        /*
+         * Otherwise, the conditional expression is a reference conditional expression.
+         * A reference conditional expression is a poly expression if it appears in an assignment context or an invocation context (§5.2. §5.3). 
+         * Otherwise, it is a standalone expression.
+         * TODO : must be implemented
+         */
         return node.getThenExpr().accept(this, solveLambdas);
     }
+    
+    private boolean isCompatible(ResolvedType resolvedType, ResolvedPrimitiveType primitiveType) {
+        return (resolvedType.isPrimitive() && resolvedType.asPrimitive().equals(primitiveType))
+        || (resolvedType.isReferenceType() && TypeHelper.isUnboxableTo(primitiveType, resolvedType.asReferenceType()));
+    }
 
     @Override
     public ResolvedType visit(EnclosedExpr node, Boolean solveLambdas) {