Merge pull request #1403 from matozoid/issue_883_var

Issue 883 var type
diff --git a/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java b/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java
index 287e88e..7b8ee87 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java
@@ -27,16 +27,13 @@
 import com.github.javaparser.ast.PackageDeclaration;
 import com.github.javaparser.ast.body.BodyDeclaration;
 import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.comments.CommentsCollection;
 import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.stmt.Statement;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.Type;
-import com.github.javaparser.ast.validator.ProblemReporter;
 import com.github.javaparser.javadoc.Javadoc;
-import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
 
 import java.io.*;
 import java.nio.charset.Charset;
@@ -53,7 +50,6 @@
  * @author Júlio Vilmar Gesser
  */
 public final class JavaParser {
-    private final CommentsInserter commentsInserter;
     private final ParserConfiguration configuration;
 
     private GeneratedJavaParser astParser = null;
@@ -74,7 +70,6 @@
      */
     public JavaParser(ParserConfiguration configuration) {
         this.configuration = configuration;
-        commentsInserter = new CommentsInserter(configuration);
     }
 
     /**
@@ -129,20 +124,13 @@
         final GeneratedJavaParser parser = getParserForProvider(provider);
         try {
             N resultNode = start.parse(parser);
-            if (configuration.isAttributeComments()) {
-                final CommentsCollection comments = parser.getCommentsCollection();
-                commentsInserter.insertComments(resultNode, comments.copy().getComments());
-            }
-            if (configuration.isLexicalPreservationEnabled()) {
-                LexicalPreservingPrinter.setup(resultNode);
-            }
-
-            configuration.getValidator().accept(resultNode, new ProblemReporter(parser.problems));
-            parser.problems.sort(PROBLEM_BY_BEGIN_POSITION);
-
             ParseResult<N> result = new ParseResult<>(resultNode, parser.problems, parser.getTokens(),
                     parser.getCommentsCollection());
-            considerInjectingSymbolResolver(result, configuration);
+
+            configuration.getPostProcessors().forEach(postProcessor ->
+                    postProcessor.process(result, configuration));
+
+            result.getProblems().sort(PROBLEM_BY_BEGIN_POSITION);
 
             return result;
         } catch (Exception e) {
@@ -531,14 +519,4 @@
     public static PackageDeclaration parsePackageDeclaration(String packageDeclaration) {
         return simplifiedParse(PACKAGE_DECLARATION, provider(packageDeclaration));
     }
-
-    private void considerInjectingSymbolResolver(ParseResult<?> parseResult, ParserConfiguration parserConfiguration) {
-        parserConfiguration.getSymbolResolver().ifPresent(symbolResolver ->
-                parseResult.getResult().ifPresent(result -> {
-                    if (result instanceof CompilationUnit) {
-                        ((CompilationUnit) result).setData(Node.SYMBOL_RESOLVER_KEY, symbolResolver);
-                    }
-                })
-        );
-    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java b/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java
index 903d401..4edc79a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java
@@ -21,6 +21,7 @@
 
 package com.github.javaparser;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.comments.CommentsCollection;
 
 import java.util.List;
@@ -28,7 +29,6 @@
 import java.util.function.Consumer;
 
 import static com.github.javaparser.utils.Utils.EOL;
-import static java.util.Collections.singletonList;
 
 /**
  * The results given when parsing with an instance of JavaParser.
@@ -54,22 +54,6 @@
     }
 
     /**
-     * Used when parsing failed completely with an exception.
-     */
-    ParseResult(Throwable throwable) {
-        this(null, singletonList(
-                new Problem(createMessage(throwable), null, throwable)), null, null);
-    }
-
-    private static String createMessage(Throwable throwable) {
-        String message = throwable.getMessage();
-        if (message == null) {
-            return throwable.getClass().getSimpleName();
-        }
-        return message;
-    }
-
-    /**
      * @return if parsing was successful, meaning no errors of any kind were encountered.
      */
     public boolean isSuccessful() {
@@ -102,7 +86,7 @@
     /**
      * @return the complete list of tokens that were parsed, or empty if parsing failed completely.
      * @deprecated lists of tokens are now kept in every node.
-     * Calling this method is comparable to calling getResult().get().getTokenRange().get() 
+     * Calling this method is comparable to calling getResult().get().getTokenRange().get()
      */
     @Deprecated
     public Optional<List<JavaToken>> getTokens() {
@@ -134,4 +118,11 @@
         }
         return message.toString();
     }
+
+    /**
+     * A post processor that can be added to ParserConfiguration to add some processing right after parsing.
+     */
+    public interface PostProcessor {
+        void process(ParseResult<? extends Node> result, ParserConfiguration configuration);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java b/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java
index f722eca..42a6fe0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java
@@ -21,10 +21,15 @@
 
 package com.github.javaparser;
 
-import com.github.javaparser.ast.validator.Java8Validator;
-import com.github.javaparser.ast.validator.Validator;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.validator.*;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
 import com.github.javaparser.resolution.SymbolResolver;
+import com.github.javaparser.version.Java10PostProcessor;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 
 import static com.github.javaparser.utils.Utils.assertNotNull;
@@ -35,6 +40,29 @@
  * It will pick up the changes.
  */
 public class ParserConfiguration {
+    public enum LanguageLevel {
+        ANY(null, null),
+        JAVA_1_0(new Java1_0Validator(), null),
+        JAVA_1_1(new Java1_1Validator(), null),
+        JAVA_1_2(new Java1_2Validator(), null),
+        JAVA_1_3(new Java1_3Validator(), null),
+        JAVA_1_4(new Java1_4Validator(), null),
+        JAVA_5(new Java5Validator(), null),
+        JAVA_6(new Java6Validator(), null),
+        JAVA_7(new Java7Validator(), null),
+        JAVA_8(new Java8Validator(), null),
+        JAVA_9(new Java9Validator(), null),
+        JAVA_10_PREVIEW(null, new Java10PostProcessor());
+
+        final Validator validator;
+        final ParseResult.PostProcessor postProcessor;
+
+        LanguageLevel(Validator validator, ParseResult.PostProcessor postProcessor) {
+            this.validator = validator;
+            this.postProcessor = postProcessor;
+        }
+    }
+
     private boolean storeTokens = true;
     private boolean attributeComments = true;
     private boolean doNotAssignCommentsPrecedingEmptyLines = true;
@@ -42,7 +70,43 @@
     private boolean lexicalPreservationEnabled = false;
     private SymbolResolver symbolResolver = null;
     private int tabSize = 1;
-    private Validator validator = new Java8Validator();
+    private LanguageLevel languageLevel;
+
+    private final List<ParseResult.PostProcessor> postProcessors = new ArrayList<>();
+
+    public ParserConfiguration() {
+        postProcessors.add((result, configuration) -> {
+            if (configuration.isLexicalPreservationEnabled()) {
+                if (configuration.isLexicalPreservationEnabled()) {
+                    result.ifSuccessful(LexicalPreservingPrinter::setup);
+                }
+            }
+        });
+        postProcessors.add((result, configuration) -> {
+            if (configuration.isAttributeComments()) {
+                result.ifSuccessful(resultNode -> result
+                        .getCommentsCollection().ifPresent(comments ->
+                                new CommentsInserter(configuration).insertComments(resultNode, comments.copy().getComments())));
+            }
+        });
+        postProcessors.add((result, configuration) -> {
+            LanguageLevel languageLevel = getLanguageLevel();
+            if (languageLevel.postProcessor != null) {
+                languageLevel.postProcessor.process(result, configuration);
+            }
+            if (languageLevel.validator != null) {
+                languageLevel.validator.accept(result.getResult().get(), new ProblemReporter(newProblem -> result.getProblems().add(newProblem)));
+            }
+        });
+        postProcessors.add((result, configuration) -> configuration.getSymbolResolver().ifPresent(symbolResolver ->
+                result.ifSuccessful(resultNode -> {
+                    if (resultNode instanceof CompilationUnit) {
+                        resultNode.setData(Node.SYMBOL_RESOLVER_KEY, symbolResolver);
+                    }
+                })
+        ));
+        setLanguageLevel(LanguageLevel.JAVA_8);
+    }
 
     public boolean isAttributeComments() {
         return attributeComments;
@@ -100,17 +164,45 @@
         return this;
     }
 
-    public Validator getValidator() {
-        return validator;
+    /**
+     * @deprecated use getLanguageLevel
+     */
+    @Deprecated
+    public Optional<Validator> getValidator() {
+        throw new IllegalStateException("method is deprecated");
     }
 
     /**
-     * The validator to run directly after parsing.
-     * By default it is {@link Java8Validator}
+     * @deprecated use setLanguageLevel, or getPostProcessors if you use a custom validator.
      */
+    @Deprecated
     public ParserConfiguration setValidator(Validator validator) {
-        assertNotNull(validator);
-        this.validator = validator;
+        // This whole method is a backwards compatability hack.
+        if (validator instanceof Java10Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_10_PREVIEW);
+        } else if (validator instanceof Java9Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_9);
+        } else if (validator instanceof Java8Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_8);
+        } else if (validator instanceof Java7Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_7);
+        } else if (validator instanceof Java6Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_6);
+        } else if (validator instanceof Java5Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_5);
+        } else if (validator instanceof Java1_4Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_1_4);
+        } else if (validator instanceof Java1_3Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_1_3);
+        } else if (validator instanceof Java1_2Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_1_2);
+        } else if (validator instanceof Java1_1Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_1_1);
+        } else if (validator instanceof Java1_0Validator) {
+            setLanguageLevel(LanguageLevel.JAVA_1_0);
+        } else if (validator instanceof NoProblemsValidator) {
+            setLanguageLevel(LanguageLevel.ANY);
+        }
         return this;
     }
 
@@ -142,4 +234,17 @@
         this.symbolResolver = symbolResolver;
         return this;
     }
+
+    public List<ParseResult.PostProcessor> getPostProcessors() {
+        return postProcessors;
+    }
+
+    public ParserConfiguration setLanguageLevel(LanguageLevel languageLevel) {
+        this.languageLevel = assertNotNull(languageLevel);
+        return this;
+    }
+
+    public LanguageLevel getLanguageLevel() {
+        return languageLevel;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java
index 400777d..285c238 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java
@@ -108,11 +108,13 @@
         /**
          * Notify exclusively for changes happening on this node alone.
          */
-        JUST_THIS_NODE, /**
+        JUST_THIS_NODE,
+        /**
          * Notify for changes happening on this node and all its descendants existing at the moment in
          * which the observer was registered. Nodes attached later will not be observed.
          */
-        THIS_NODE_AND_EXISTING_DESCENDANTS, /**
+        THIS_NODE_AND_EXISTING_DESCENDANTS,
+        /**
          * Notify for changes happening on this node and all its descendants. The descendants existing at the moment in
          * which the observer was registered will be observed immediately. As new nodes are attached later they are
          * automatically registered to be observed.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AssignExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AssignExpr.java
index db03718..fbb4687 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AssignExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AssignExpr.java
@@ -24,19 +24,14 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-
 import static com.github.javaparser.utils.Utils.assertNotNull;
-
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.AssignExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.printer.Printable;
-
 import javax.annotation.Generated;
-
 import com.github.javaparser.TokenRange;
-
 import java.util.function.Consumer;
 import java.util.Optional;
 
@@ -78,7 +73,7 @@
         }
 
         public Optional<BinaryExpr.Operator> toBinaryOperator() {
-            switch (this) {
+            switch(this) {
                 case PLUS:
                     return Optional.of(BinaryExpr.Operator.PLUS);
                 case MINUS:
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BinaryExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BinaryExpr.java
index ac4729a..5ec79c0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BinaryExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BinaryExpr.java
@@ -24,19 +24,14 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-
 import static com.github.javaparser.utils.Utils.assertNotNull;
-
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.BinaryExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.printer.Printable;
-
 import javax.annotation.Generated;
-
 import com.github.javaparser.TokenRange;
-
 import java.util.function.Consumer;
 import java.util.Optional;
 
@@ -83,7 +78,7 @@
         }
 
         public Optional<AssignExpr.Operator> toAssignOperator() {
-            switch (this) {
+            switch(this) {
                 case BINARY_OR:
                     return Optional.of(AssignExpr.Operator.BINARY_OR);
                 case BINARY_AND:
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ObjectCreationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ObjectCreationExpr.java
index 7b702c5..c4fe045 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ObjectCreationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ObjectCreationExpr.java
@@ -32,8 +32,6 @@
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Optional;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import com.github.javaparser.ast.Node;
@@ -44,7 +42,6 @@
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import java.util.function.Consumer;
 
 /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java
index 05452bd..76dba1f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java
@@ -61,7 +61,8 @@
         /**
          * The [] were found on the name, like "int a[]" or "String abc()[][]"
          */
-        NAME, /**
+        NAME,
+        /**
          * The [] were found on the type, like "int[] a" or "String[][] abc()"
          */
         TYPE
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java
index b28db1d..acaf5a9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java
@@ -349,4 +349,23 @@
     public Optional<WildcardType> toWildcardType() {
         return Optional.empty();
     }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isVarType() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public VarType asVarType() {
+        throw new IllegalStateException(f("%s is not an VarType", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<VarType> toVarType() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifVarType(Consumer<VarType> action) {
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java
new file mode 100644
index 0000000..0d62966
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of JavaParser.
+ *
+ * JavaParser can be used either under the terms of
+ * a) the GNU Lesser General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ * b) the terms of the Apache License
+ *
+ * You should have received a copy of both licenses in LICENCE.LGPL and
+ * LICENCE.APACHE. Please refer to those files for details.
+ *
+ * JavaParser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+package com.github.javaparser.ast.type;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.metamodel.VoidTypeMetaModel;
+import com.github.javaparser.resolution.types.ResolvedVoidType;
+import javax.annotation.Generated;
+import java.util.Optional;
+import java.util.function.Consumer;
+import com.github.javaparser.metamodel.VarTypeMetaModel;
+
+public final class VarType extends Type {
+
+    @AllFieldsConstructor
+    public VarType() {
+        this(null);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public VarType(TokenRange tokenRange) {
+        super(tokenRange);
+        customInitialization();
+    }
+
+    @Override
+    public VarType setAnnotations(NodeList<AnnotationExpr> annotations) {
+        return (VarType) super.setAnnotations(annotations);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        return super.remove(node);
+    }
+
+    @Override
+    public String asString() {
+        return "var";
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public VarType clone() {
+        return (VarType) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public VarTypeMetaModel getMetaModel() {
+        return JavaParserMetaModel.varTypeMetaModel;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    public ResolvedVoidType resolve() {
+        return getSymbolResolver().toResolvedType(this, ResolvedVoidType.class);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
+    public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) {
+        return v.visit(this, arg);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
+    public <A> void accept(final VoidVisitor<A> v, final A arg) {
+        v.visit(this, arg);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isVarType() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public VarType asVarType() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<VarType> toVarType() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifVarType(Consumer<VarType> action) {
+        action.accept(this);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java10Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java10Validator.java
new file mode 100644
index 0000000..c551013
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java10Validator.java
@@ -0,0 +1,20 @@
+package com.github.javaparser.ast.validator;
+
+import com.github.javaparser.ast.type.VarType;
+
+/**
+ * This validator validates according to Java 10 syntax rules.
+ */
+public class Java10Validator extends Java9Validator {
+
+    protected final Validator varOnlyOnLocalVariableDefinitionAndFor = new SingleNodeTypeValidator<>(VarType.class, (n, reporter) -> {
+
+    });
+
+    public Java10Validator() {
+        super();
+        add(varOnlyOnLocalVariableDefinitionAndFor);
+        /* There is no validator that validates that "var" is not used in Java 9 and lower, since the parser will never create a VarType node,
+           because that is done by the Java10 postprocessor. You can add it by hand, but that is obscure enough to ignore. */
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/NoProblemsValidator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/NoProblemsValidator.java
index ceecf17..15edbf7 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/NoProblemsValidator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/NoProblemsValidator.java
@@ -1,10 +1,14 @@
 package com.github.javaparser.ast.validator;
 
+import com.github.javaparser.ParserConfiguration;
 import com.github.javaparser.ast.Node;
 
 /**
  * Stub validator for when no validation is wanted.
+ *
+ * @deprecated when setting a language validator, try {@link com.github.javaparser.ParserConfiguration#setLanguageLevel(ParserConfiguration.LanguageLevel)} with ANY.
  */
+@Deprecated
 public final class NoProblemsValidator implements Validator {
     @Override
     public void accept(Node node, ProblemReporter problemReporter) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ProblemReporter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ProblemReporter.java
index f5dc663..eb54810 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ProblemReporter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ProblemReporter.java
@@ -4,7 +4,7 @@
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.ast.nodeTypes.NodeWithTokenRange;
 
-import java.util.List;
+import java.util.function.Consumer;
 
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
@@ -12,10 +12,10 @@
  * A simple interface where validators can report found problems.
  */
 public class ProblemReporter {
-    private final List<Problem> problems;
+    private final Consumer<Problem> problemConsumer;
 
-    public ProblemReporter(List<Problem> problems) {
-        this.problems = problems;
+    public ProblemReporter(Consumer<Problem> problemConsumer) {
+        this.problemConsumer = problemConsumer;
     }
 
     /**
@@ -29,6 +29,6 @@
     }
 
     public void report(TokenRange range, String message, Object... args) {
-        problems.add(new Problem(f(message, args), range, null));
+        problemConsumer.accept(new Problem(f(message, args), range, null));
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/TypedValidator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/TypedValidator.java
index e6db75f..588c53f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/TypedValidator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/TypedValidator.java
@@ -1,5 +1,6 @@
 package com.github.javaparser.ast.validator;
 
+import com.github.javaparser.ParseResult;
 import com.github.javaparser.ast.Node;
 
 import java.util.function.BiConsumer;
@@ -13,4 +14,11 @@
      * @param problemReporter when found, validation errors can be reported here
      */
     void accept(N node, ProblemReporter problemReporter);
+
+    @SuppressWarnings("unchecked")
+    default ParseResult.PostProcessor postProcessor() {
+        return (result, configuration) ->
+                result.getResult().ifPresent(node ->
+                        accept((N) node, new ProblemReporter(problem -> result.getProblems().add(problem))));
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/CloneVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/CloneVisitor.java
index e5b88e1..4ae343a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/CloneVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/CloneVisitor.java
@@ -1068,4 +1068,13 @@
         r.setComment(comment);
         return r;
     }
+
+    @Override
+    public Visitable visit(final VarType n, final Object arg) {
+        NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
+        Comment comment = cloneNode(n.getComment(), arg);
+        VarType r = new VarType(n.getTokenRange().orElse(null));
+        r.setComment(comment);
+        return r;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java
index 49a2ee2..2062185 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java
@@ -1376,4 +1376,14 @@
             return false;
         return true;
     }
+
+    @Override
+    public Boolean visit(final VarType n, final Visitable arg) {
+        final VarType n2 = (VarType) arg;
+        if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
+            return false;
+        if (!nodeEquals(n.getComment(), n2.getComment()))
+            return false;
+        return true;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericListVisitorAdapter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericListVisitorAdapter.java
index 14ae6c5..2defdfa 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericListVisitorAdapter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericListVisitorAdapter.java
@@ -2041,4 +2041,21 @@
         }
         return result;
     }
+
+    @Override
+    public List<R> visit(final VarType n, final A arg) {
+        List<R> result = new ArrayList<>();
+        List<R> tmp;
+        {
+            tmp = n.getAnnotations().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        if (n.getComment().isPresent()) {
+            tmp = n.getComment().get().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        return result;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitor.java
index 3fa06f3..494013c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitor.java
@@ -314,4 +314,6 @@
 
     @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ReceiverParameter n, A arg);
+
+    R visit(VarType n, A arg);
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorAdapter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorAdapter.java
index 5b4bf55..3d5de4f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorAdapter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorAdapter.java
@@ -2035,4 +2035,20 @@
         }
         return null;
     }
+
+    @Override
+    public R visit(final VarType n, final A arg) {
+        R result;
+        {
+            result = n.getAnnotations().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        if (n.getComment().isPresent()) {
+            result = n.getComment().get().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        return null;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorWithDefaults.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorWithDefaults.java
index 1f93628..2cd9a0f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorWithDefaults.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/GenericVisitorWithDefaults.java
@@ -595,4 +595,9 @@
     public R visit(final ReceiverParameter n, final A arg) {
         return defaultAction(n, arg);
     }
+
+    @Override
+    public R visit(final VarType n, final A arg) {
+        return defaultAction(n, arg);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/HashCodeVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/HashCodeVisitor.java
index 2a12b7f..92da13e 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/HashCodeVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/HashCodeVisitor.java
@@ -510,4 +510,9 @@
     public Integer visit(final ReceiverParameter n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
+
+    @Override
+    public Integer visit(final VarType n, final Void arg) {
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ModifierVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ModifierVisitor.java
index ae82fc2..c780864 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ModifierVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ModifierVisitor.java
@@ -1285,4 +1285,13 @@
         n.setComment(comment);
         return n;
     }
+
+    @Override
+    public Visitable visit(final VarType n, final A arg) {
+        NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
+        Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
+        n.setAnnotations(annotations);
+        n.setComment(comment);
+        return n;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitor.java
index 8e68629..b3c1dce 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitor.java
@@ -1143,4 +1143,12 @@
             return false;
         return true;
     }
+
+    @Override
+    public Boolean visit(final VarType n, final Visitable arg) {
+        final VarType n2 = (VarType) arg;
+        if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
+            return false;
+        return true;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitor.java
index 914391c..774e5d9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitor.java
@@ -502,4 +502,9 @@
     public Integer visit(final ReceiverParameter n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg));
     }
+
+    @Override
+    public Integer visit(final VarType n, final Void arg) {
+        return (n.getAnnotations().accept(this, arg));
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityEqualsVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityEqualsVisitor.java
index dceeabb..7c642bb 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityEqualsVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityEqualsVisitor.java
@@ -588,4 +588,9 @@
     public Boolean visit(final ReceiverParameter n, final Visitable arg) {
         return n == arg;
     }
+
+    @Override
+    public Boolean visit(final VarType n, final Visitable arg) {
+        return n == arg;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityHashCodeVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityHashCodeVisitor.java
index 8f7a5e3..c53cf79 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityHashCodeVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/ObjectIdentityHashCodeVisitor.java
@@ -502,4 +502,9 @@
     public Integer visit(final ReceiverParameter n, final Void arg) {
         return n.hashCode();
     }
+
+    @Override
+    public Integer visit(final VarType n, final Void arg) {
+        return n.hashCode();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitor.java
index e797d8e..37c9c1c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitor.java
@@ -309,4 +309,6 @@
 
     @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ReceiverParameter n, A arg);
+
+    void visit(VarType n, A arg);
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorAdapter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorAdapter.java
index d0cfbe4..1ee8266 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorAdapter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorAdapter.java
@@ -764,4 +764,10 @@
         n.getType().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
+
+    @Override
+    public void visit(final VarType n, final A arg) {
+        n.getAnnotations().forEach(p -> p.accept(this, arg));
+        n.getComment().ifPresent(l -> l.accept(this, arg));
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorWithDefaults.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorWithDefaults.java
index ba5a93d..6622567 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorWithDefaults.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/VoidVisitorWithDefaults.java
@@ -591,4 +591,9 @@
     public void visit(final ReceiverParameter n, final A arg) {
         defaultAction(n, arg);
     }
+
+    @Override
+    public void visit(final VarType n, final A arg) {
+        defaultAction(n, arg);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/JavaParserMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/JavaParserMetaModel.java
index 4d81ec6..bffbd37 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/JavaParserMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/JavaParserMetaModel.java
@@ -349,6 +349,7 @@
         nodeMetaModels.add(unionTypeMetaModel);
         nodeMetaModels.add(unknownTypeMetaModel);
         nodeMetaModels.add(unparsableStmtMetaModel);
+        nodeMetaModels.add(varTypeMetaModel);
         nodeMetaModels.add(variableDeclarationExprMetaModel);
         nodeMetaModels.add(variableDeclaratorMetaModel);
         nodeMetaModels.add(voidTypeMetaModel);
@@ -441,7 +442,7 @@
         fieldDeclarationMetaModel.getDeclaredPropertyMetaModels().add(fieldDeclarationMetaModel.modifiersPropertyMetaModel);
         fieldDeclarationMetaModel.variablesPropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "variables", com.github.javaparser.ast.body.VariableDeclarator.class, Optional.of(variableDeclaratorMetaModel), false, true, true, false, false);
         fieldDeclarationMetaModel.getDeclaredPropertyMetaModels().add(fieldDeclarationMetaModel.variablesPropertyMetaModel);
-        fieldDeclarationMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        fieldDeclarationMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, false, false, false);
         fieldDeclarationMetaModel.getDerivedPropertyMetaModels().add(fieldDeclarationMetaModel.maximumCommonTypePropertyMetaModel);
         initializerDeclarationMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(initializerDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false, false);
         initializerDeclarationMetaModel.getDeclaredPropertyMetaModels().add(initializerDeclarationMetaModel.bodyPropertyMetaModel);
@@ -605,7 +606,7 @@
         variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.modifiersPropertyMetaModel);
         variableDeclarationExprMetaModel.variablesPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "variables", com.github.javaparser.ast.body.VariableDeclarator.class, Optional.of(variableDeclaratorMetaModel), false, true, true, false, false);
         variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.variablesPropertyMetaModel);
-        variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, false, false, false);
         variableDeclarationExprMetaModel.getDerivedPropertyMetaModels().add(variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel);
         importDeclarationMetaModel.isAsteriskPropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "isAsterisk", boolean.class, Optional.empty(), false, false, false, false, false);
         importDeclarationMetaModel.getDeclaredPropertyMetaModels().add(importDeclarationMetaModel.isAsteriskPropertyMetaModel);
@@ -956,6 +957,8 @@
 
     public static final WildcardTypeMetaModel wildcardTypeMetaModel = new WildcardTypeMetaModel(Optional.of(typeMetaModel));
 
+    public static final VarTypeMetaModel varTypeMetaModel = new VarTypeMetaModel(Optional.of(typeMetaModel));
+
     public static final ModuleRequiresStmtMetaModel moduleRequiresStmtMetaModel = new ModuleRequiresStmtMetaModel(Optional.of(moduleStmtMetaModel));
 
     public static final ModuleExportsStmtMetaModel moduleExportsStmtMetaModel = new ModuleExportsStmtMetaModel(Optional.of(moduleStmtMetaModel));
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/VarTypeMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/VarTypeMetaModel.java
new file mode 100644
index 0000000..1ada830
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/VarTypeMetaModel.java
@@ -0,0 +1,10 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class VarTypeMetaModel extends TypeMetaModel {
+
+    VarTypeMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.type.VarType.class, "VarType", "com.github.javaparser.ast.type", false, false);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java b/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java
index 3fac25c..8d3fca9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java
@@ -793,6 +793,8 @@
 
         concreteSyntaxModelByClass.put(VoidType.class, sequence(comment(), annotations(), token(GeneratedJavaParserConstants.VOID)));
 
+        concreteSyntaxModelByClass.put(VarType.class, sequence(comment(), annotations(), string(GeneratedJavaParserConstants.IDENTIFIER, "var")));
+
         concreteSyntaxModelByClass.put(WildcardType.class, sequence(comment(), annotations(), token(GeneratedJavaParserConstants.HOOK),
                 CsmElement.conditional(ObservableProperty.EXTENDED_TYPE, IS_PRESENT, CsmElement.sequence(space(), token(GeneratedJavaParserConstants.EXTENDS), space(), CsmElement.child(EXTENDED_TYPE))),
                 CsmElement.conditional(ObservableProperty.SUPER_TYPE, IS_PRESENT, CsmElement.sequence(space(), token(GeneratedJavaParserConstants.SUPER), space(), CsmElement.child(SUPER_TYPE)))));
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java
index 3a09cbf..d68f387 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java
@@ -559,6 +559,13 @@
     }
 
     @Override
+    public void visit(final VarType n, final Void arg) {
+        printComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printer.print("var");
+    }
+
+    @Override
     public void visit(final ArrayAccessExpr n, final Void arg) {
         printComment(n.getComment(), arg);
         n.getName().accept(this, arg);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/version/Java10PostProcessor.java b/javaparser-core/src/main/java/com/github/javaparser/version/Java10PostProcessor.java
new file mode 100644
index 0000000..569f461
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/version/Java10PostProcessor.java
@@ -0,0 +1,30 @@
+package com.github.javaparser.version;
+
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.VarType;
+import com.github.javaparser.ast.validator.Java10Validator;
+import com.github.javaparser.ast.validator.ProblemReporter;
+import com.github.javaparser.ast.visitor.ModifierVisitor;
+import com.github.javaparser.ast.visitor.Visitable;
+
+/**
+ * Processes the generic AST into a Java 10 AST and validates it.
+ */
+public class Java10PostProcessor implements ParseResult.PostProcessor {
+    private final Java10Validator validator = new Java10Validator();
+
+    @Override
+    public void process(ParseResult<? extends Node> result, ParserConfiguration configuration) {
+        result.getResult().ifPresent(node -> {
+            node.findAll(ClassOrInterfaceType.class).forEach(n -> {
+                if (n.getNameAsString().equals("var")) {
+                    n.replace(new VarType(n.getTokenRange().orElse(null)));
+                }
+            });
+            validator.accept(node, new ProblemReporter(problem -> result.getProblems().add(problem)));
+        });
+    }
+}
diff --git a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
index 15772b3..43d9112 100644
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
+++ b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
@@ -140,6 +140,7 @@
         add(UnknownType.class);
         add(VoidType.class);
         add(WildcardType.class);
+        add(VarType.class);
 
         add(ModuleRequiresStmt.class);
         add(ModuleExportsStmt.class);
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java
index dc9d862..499ef3b 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java
@@ -467,4 +467,9 @@
     public ResolvedType visit(ReceiverParameter node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
+
+    @Override
+    public ResolvedType visit(VarType node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
 }
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
index ab4bb74..33c9208 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
@@ -2,9 +2,14 @@
 
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.validator.NoProblemsValidator;
 import org.junit.Test;
 
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
 import static com.github.javaparser.Providers.provider;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -12,8 +17,18 @@
     @Test
     public void storeNoTokens() {
         ParseResult<CompilationUnit> result = new JavaParser(new ParserConfiguration().setStoreTokens(false)).parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
-        
+
         assertFalse(result.getTokens().isPresent());
         assertTrue(result.getResult().get().findAll(Node.class).stream().noneMatch(node -> node.getTokenRange().isPresent()));
     }
+
+    @Test
+    public void noProblemsHere() {
+        ParseResult<Statement> result =
+                new JavaParser(new ParserConfiguration().setLanguageLevel(ANY))
+                        .parse(STATEMENT, provider("try{}"));
+        assertEquals(true, result.isSuccessful());
+    }
+
+
 }
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
index 77c3d97..aa21172 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
@@ -6,11 +6,13 @@
 import com.github.javaparser.ParserConfiguration;
 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
 import com.github.javaparser.ast.validator.Java5Validator;
+import com.github.javaparser.ast.validator.ProblemReporter;
 import org.junit.Test;
 
 import static com.github.javaparser.JavaParser.parseType;
 import static com.github.javaparser.JavaParser.parseVariableDeclarationExpr;
 import static com.github.javaparser.ParseStart.VARIABLE_DECLARATION_EXPR;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
 import static com.github.javaparser.Providers.provider;
 import static org.junit.Assert.*;
 
@@ -30,10 +32,11 @@
 
     @Test
     public void primitiveTypeArgumentLenientValidator() {
-        ParserConfiguration config = new ParserConfiguration();
-        config.setValidator(new Java5Validator() {{
+        ParserConfiguration config = new ParserConfiguration()
+                .setLanguageLevel(ANY);
+        config.getPostProcessors().add(new Java5Validator() {{
             remove(noPrimitiveGenericArguments);
-        }});
+        }}.postProcessor());
 
         ParseResult<VariableDeclarationExpr> result = new JavaParser(config).parse(
                 VARIABLE_DECLARATION_EXPR, provider("List<long> x"));
@@ -56,7 +59,7 @@
         type.ifArrayType(t -> s[0] = t);
         assertNotNull(s[0]);
     }
-    
+
     @Test
     public void issue1251() {
         final Type type = parseType("TypeUtilsTest<String>.Tester");
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
index 09eb39d..6606d2e 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
@@ -91,7 +91,7 @@
     public void nonEmptyList() {
         ArrayCreationExpr expr = new ArrayCreationExpr(PrimitiveType.booleanType());
         List<Problem> problems= new ArrayList<>();
-        new Java1_0Validator().accept(expr, new ProblemReporter(problems));
+        new Java1_0Validator().accept(expr, new ProblemReporter(problems::add));
         assertEquals("ArrayCreationExpr.levels can not be empty.", problems.get(0).getMessage());
     }
 }
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
index 6bf000d..a2a03f8 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
@@ -5,7 +5,6 @@
 import com.github.javaparser.ParserConfiguration;
 import com.github.javaparser.Problem;
 import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.stmt.Statement;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
@@ -13,19 +12,17 @@
 import org.junit.Test;
 
 import java.util.*;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
 
 import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
 import static com.github.javaparser.ParseStart.EXPRESSION;
 import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
 import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertCollections;
 import static com.github.javaparser.utils.TestUtils.assertNoProblems;
 import static com.github.javaparser.utils.TestUtils.assertProblems;
 
 public class Java7ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setValidator(new Java7Validator()));
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_7));
 
     @Test
     public void generics() {
@@ -86,7 +83,7 @@
         UnionType unionType = new UnionType();
 
         List<Problem> problems = new ArrayList<>();
-        javaParser.getParserConfiguration().getValidator().accept(unionType, new ProblemReporter(problems));
+        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
         
         assertProblems(problems, "UnionType.elements can not be empty.");
     }
@@ -97,7 +94,7 @@
         unionType.getElements().add(new ClassOrInterfaceType());
 
         List<Problem> problems = new ArrayList<>();
-        javaParser.getParserConfiguration().getValidator().accept(unionType, new ProblemReporter(problems));
+        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
         
         assertProblems(problems, "Union type (multi catch) must have at least two elements.");
     }
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/ValidatorTest.java
deleted file mode 100644
index be87ec1..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/ValidatorTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.github.javaparser.ast.validator;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.STATEMENT;
-import static com.github.javaparser.Providers.provider;
-import static org.junit.Assert.assertEquals;
-
-public class ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setValidator(new Java9Validator()));
-
-    @Test
-    public void noProblemsHere() {
-        ParseResult<Statement> result =
-                new JavaParser(new ParserConfiguration().setValidator(new NoProblemsValidator()))
-                        .parse(STATEMENT, provider("try{}"));
-        assertEquals(true, result.isSuccessful());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
index fff0171..a0bb50e 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
@@ -6,10 +6,8 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.nio.file.Path;
 import java.util.List;
-import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -19,7 +17,7 @@
     private final SourceRoot sourceRoot = new SourceRoot(root);
 
     @Test
-    public void parseTestDirectory() throws URISyntaxException, IOException {
+    public void parseTestDirectory() throws IOException {
 
         List<ParseResult<CompilationUnit>> parseResults = sourceRoot.tryToParse();
         List<CompilationUnit> units = sourceRoot.getCompilationUnits();
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/TestUtils.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
index dc96f7c..0213c11 100644
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
+++ b/javaparser-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
@@ -20,6 +20,7 @@
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import static com.github.javaparser.utils.Utils.EOL;
 import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock;
+import static java.util.Arrays.*;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -130,8 +131,7 @@
 
     public static void assertProblems(List<Problem> result, String... expectedArg) {
         Set<String> actual = result.stream().map(Problem::toString).collect(Collectors.toSet());
-        Set<String> expected = new HashSet<>();
-        expected.addAll(Arrays.asList(expectedArg));
+        Set<String> expected = new HashSet<>(asList(expectedArg));
         assertCollections(expected, actual);
     }
 
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java
new file mode 100644
index 0000000..87f7990
--- /dev/null
+++ b/javaparser-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java
@@ -0,0 +1,47 @@
+package com.github.javaparser.version;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.VarType;
+import org.junit.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10_PREVIEW;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class Java10PostProcessorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_10_PREVIEW));
+
+    @Test
+    public void varIsAType() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var x=\"\";"));
+
+        List<VarType> allVarTypes = result.getResult().get().findAll(VarType.class);
+
+        assertEquals(1, allVarTypes.size());
+    }
+
+    @Test
+    public void varAllowedInLocalVariableDeclaration() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a = 5;"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    public void varAllowedInForEach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(var a : as){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    public void varAllowedInOldFor() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(var a = 5;a<9;a++){}"));
+        assertNoProblems(result);
+    }
+}