1 package com.github.javaparser.symbolsolver.resolution.typeinference; 2 3 import com.github.javaparser.ast.Node; 4 import com.github.javaparser.ast.expr.*; 5 import com.github.javaparser.ast.stmt.BlockStmt; 6 import com.github.javaparser.ast.stmt.ExpressionStmt; 7 import com.github.javaparser.ast.stmt.ReturnStmt; 8 import com.github.javaparser.ast.type.UnknownType; 9 import com.github.javaparser.resolution.types.ResolvedType; 10 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; 11 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 12 13 import java.util.List; 14 15 /** 16 * @author Federico Tomassetti 17 */ 18 public class ExpressionHelper { 19 20 /** 21 * See https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.2 22 * @return 23 */ isStandaloneExpression(Expression expression)24 public static boolean isStandaloneExpression(Expression expression) { 25 return !isPolyExpression(expression); 26 } 27 28 /** 29 * See https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.2 30 * @return 31 */ isPolyExpression(Expression expression)32 public static boolean isPolyExpression(Expression expression) { 33 if (expression instanceof EnclosedExpr) { 34 throw new UnsupportedOperationException(expression.toString()); 35 } 36 if (expression instanceof ObjectCreationExpr) { 37 // A class instance creation expression is a poly expression (§15.2) if it uses the diamond form for type 38 // arguments to the class, and it appears in an assignment context or an invocation context (§5.2, §5.3). 39 // Otherwise, it is a standalone expression. 40 ObjectCreationExpr objectCreationExpr = (ObjectCreationExpr)expression; 41 if (objectCreationExpr.isUsingDiamondOperator()) { 42 throw new UnsupportedOperationException(expression.toString()); 43 } else { 44 return false; 45 } 46 } 47 if (expression instanceof MethodCallExpr) { 48 MethodCallExpr methodCallExpr = (MethodCallExpr)expression; 49 50 // A method invocation expression is a poly expression if all of the following are true: 51 // 52 // 1. The invocation appears in an assignment context or an invocation context (§5.2, §5.3). 53 54 if (!appearsInAssignmentContext(expression) || appearsInInvocationContext(expression)) { 55 return false; 56 } 57 58 // 2. If the invocation is qualified (that is, any form of MethodInvocation except for the first), then 59 // the invocation elides TypeArguments to the left of the Identifier. 60 61 if (isQualified(methodCallExpr) && !elidesTypeArguments(methodCallExpr)) { 62 return false; 63 } 64 65 // 3. The method to be invoked, as determined by the following subsections, is generic (§8.4.4) and has a 66 // return type that mentions at least one of the method's type parameters. 67 68 //boolean condition3 =; 69 throw new UnsupportedOperationException(expression.toString()); 70 71 // Otherwise, the method invocation expression is a standalone expression. 72 //return true; 73 } 74 if (expression instanceof MethodReferenceExpr) { 75 throw new UnsupportedOperationException(expression.toString()); 76 } 77 if (expression instanceof ConditionalExpr) { 78 throw new UnsupportedOperationException(expression.toString()); 79 } 80 if (expression instanceof LambdaExpr) { 81 return true; 82 } 83 return false; 84 } 85 elidesTypeArguments(MethodCallExpr methodCall)86 private static boolean elidesTypeArguments(MethodCallExpr methodCall) { 87 throw new UnsupportedOperationException(); 88 } 89 isQualified(MethodCallExpr methodCall)90 private static boolean isQualified(MethodCallExpr methodCall) { 91 throw new UnsupportedOperationException(); 92 } 93 94 // Not sure if should look if the parent is an assignment context appearsInAssignmentContext(Expression expression)95 private static boolean appearsInAssignmentContext(Expression expression) { 96 if (expression.getParentNode().isPresent()) { 97 Node parent = expression.getParentNode().get(); 98 if (parent instanceof ExpressionStmt) { 99 return false; 100 } 101 if (parent instanceof MethodCallExpr) { 102 return false; 103 } 104 if (parent instanceof ReturnStmt) { 105 return false; 106 } 107 throw new UnsupportedOperationException(parent.getClass().getCanonicalName()); 108 } 109 return false; 110 } 111 appearsInInvocationContext(Expression expression)112 private static boolean appearsInInvocationContext(Expression expression) { 113 if (expression.getParentNode().isPresent()) { 114 Node parent = expression.getParentNode().get(); 115 if (parent instanceof ExpressionStmt) { 116 return false; 117 } 118 if (parent instanceof MethodCallExpr) { 119 return true; 120 } 121 throw new UnsupportedOperationException(parent.getClass().getCanonicalName()); 122 } 123 return false; 124 } 125 isExplicitlyTyped(LambdaExpr lambdaExpr)126 public static boolean isExplicitlyTyped(LambdaExpr lambdaExpr) { 127 return lambdaExpr.getParameters().stream().allMatch(p -> !(p.getType() instanceof UnknownType)); 128 } 129 getResultExpressions(BlockStmt blockStmt)130 public static List<Expression> getResultExpressions(BlockStmt blockStmt) { 131 throw new UnsupportedOperationException(); 132 } 133 isCompatibleInAssignmentContext(Expression expression, ResolvedType type, TypeSolver typeSolver)134 public static boolean isCompatibleInAssignmentContext(Expression expression, ResolvedType type, TypeSolver typeSolver) { 135 return type.isAssignableBy(JavaParserFacade.get(typeSolver).getType(expression, false)); 136 } 137 } 138