Home | History | Annotate | Download | only in chunks
      1 package com.github.javaparser.ast.validator.chunks;
      2 
      3 import com.github.javaparser.ast.Node;
      4 import com.github.javaparser.ast.body.Parameter;
      5 import com.github.javaparser.ast.body.VariableDeclarator;
      6 import com.github.javaparser.ast.expr.ArrayCreationExpr;
      7 import com.github.javaparser.ast.expr.LambdaExpr;
      8 import com.github.javaparser.ast.expr.NullLiteralExpr;
      9 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
     10 import com.github.javaparser.ast.stmt.ExpressionStmt;
     11 import com.github.javaparser.ast.stmt.ForStmt;
     12 import com.github.javaparser.ast.stmt.ForeachStmt;
     13 import com.github.javaparser.ast.type.VarType;
     14 import com.github.javaparser.ast.validator.ProblemReporter;
     15 import com.github.javaparser.ast.validator.TypedValidator;
     16 
     17 import java.util.Optional;
     18 
     19 public class VarValidator implements TypedValidator<VarType> {
     20     private boolean varAllowedInLambdaParameters;
     21 
     22     public VarValidator(boolean varAllowedInLambdaParameters) {
     23         this.varAllowedInLambdaParameters = varAllowedInLambdaParameters;
     24     }
     25 
     26     @Override
     27     public void accept(VarType node, ProblemReporter reporter) {
     28         // All allowed locations are within a VariableDeclaration inside a VariableDeclarationExpr inside something else.
     29         Optional<VariableDeclarator> variableDeclarator = node.findParent(VariableDeclarator.class);
     30         if (!variableDeclarator.isPresent()) {
     31             // Java 11's var in lambda's
     32             if (varAllowedInLambdaParameters) {
     33                 boolean valid = node
     34                         .findParent(Parameter.class)
     35                         .flatMap(Node::getParentNode)
     36                         .map((Node p) -> p instanceof LambdaExpr).orElse(false);
     37                 if (valid) {
     38                     return;
     39                 }
     40             }
     41             reportIllegalPosition(node, reporter);
     42             return;
     43         }
     44         variableDeclarator.ifPresent(vd -> {
     45             Optional<Node> variableDeclarationExpr = vd.getParentNode();
     46             if (!variableDeclarationExpr.isPresent()) {
     47                 reportIllegalPosition(node, reporter);
     48                 return;
     49             }
     50             variableDeclarationExpr.ifPresent(vdeNode -> {
     51                 if (!(vdeNode instanceof VariableDeclarationExpr)) {
     52                     reportIllegalPosition(node, reporter);
     53                     return;
     54                 }
     55                 VariableDeclarationExpr vde = (VariableDeclarationExpr) vdeNode;
     56                 if (vde.getVariables().size() > 1) {
     57                     reporter.report(vde, "\"var\" only takes a single variable.");
     58                 }
     59                 Optional<Node> container = vdeNode.getParentNode();
     60                 if (!container.isPresent()) {
     61                     reportIllegalPosition(node, reporter);
     62                     return;
     63                 }
     64                 container.ifPresent(c -> {
     65                     boolean positionIsFine = c instanceof ForStmt || c instanceof ForeachStmt || c instanceof ExpressionStmt;
     66                     if (!positionIsFine) {
     67                         reportIllegalPosition(node, reporter);
     68                     }
     69                     // A local variable declaration ends up inside an ExpressionStmt.
     70                     if (c instanceof ExpressionStmt) {
     71                         if (!vd.getInitializer().isPresent()) {
     72                             reporter.report(node, "\"var\" needs an initializer.");
     73                         }
     74                         vd.getInitializer().ifPresent(initializer -> {
     75                             if (initializer instanceof NullLiteralExpr) {
     76                                 reporter.report(node, "\"var\" cannot infer type from just null.");
     77                             }
     78                             if (initializer instanceof ArrayCreationExpr) {
     79                                 reporter.report(node, "\"var\" cannot infer array types.");
     80                             }
     81                         });
     82 
     83                     }
     84                 });
     85             });
     86         });
     87 
     88     }
     89 
     90     private void reportIllegalPosition(VarType n, ProblemReporter reporter) {
     91         reporter.report(n, "\"var\" is not allowed here.");
     92     }
     93 }
     94