Throw something together for VoidVisitor
diff --git a/javaparser-bootstrap/pom.xml b/javaparser-bootstrap/pom.xml
new file mode 100644
index 0000000..abe10a8
--- /dev/null
+++ b/javaparser-bootstrap/pom.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>javaparser-parent</artifactId>
+        <groupId>com.github.javaparser</groupId>
+        <version>3.0.1-RC.2-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>javaparser-bootstrap</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/javaparser-bootstrap/src/main/java/com/github/javaparser/bootstrap/VisitorGenerator.java b/javaparser-bootstrap/src/main/java/com/github/javaparser/bootstrap/VisitorGenerator.java
new file mode 100644
index 0000000..72e4095
--- /dev/null
+++ b/javaparser-bootstrap/src/main/java/com/github/javaparser/bootstrap/VisitorGenerator.java
@@ -0,0 +1,36 @@
+package com.github.javaparser.bootstrap;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.model.JavaParserModel;
+import com.github.javaparser.model.NodeModel;
+
+import static com.github.javaparser.ast.Modifier.PUBLIC;
+import static com.github.javaparser.ast.NodeList.nodeList;
+
+public class VisitorGenerator {
+    private static JavaParserModel javaParserModel = new JavaParserModel();
+
+    public static void main(String[] args) {
+        CompilationUnit cu = new CompilationUnit("com.github.javaparser.ast.visitor");
+        cu.addImport("com.github.javaparser.ast.*");
+        cu.addImport("com.github.javaparser.ast.body.*");
+        cu.addImport("com.github.javaparser.ast.comments.*");
+        cu.addImport("com.github.javaparser.ast.expr.*");
+        cu.addImport("com.github.javaparser.ast.imports.*");
+        cu.addImport("com.github.javaparser.ast.stmt.*");
+        cu.addImport("com.github.javaparser.ast.type.*");
+
+        ClassOrInterfaceDeclaration visitor = cu.addInterface("VoidVisitor", PUBLIC);
+        visitor.setTypeParameters(nodeList(new TypeParameter("A")));
+
+        for (NodeModel node : javaParserModel.getNodeModels()) {
+            visitor.addMethod("visit")
+                    .addParameter(node.getClassName(), "n")
+                    .addParameter("A", "arg");
+        }
+
+        System.out.println(cu);
+    }
+}
diff --git a/javaparser-core/list_nodes.sh b/javaparser-core/list_nodes.sh
new file mode 100755
index 0000000..475d71d
--- /dev/null
+++ b/javaparser-core/list_nodes.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+ls -1 src/main/java/com/github/javaparser/ast/*|sed "s|src/main/java/com/github/javaparser/ast/||"|sed "s/\(.*\)\.java/add(\1.class),/" > nodes.txt
+
+
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java b/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java
index 55e635a..d31aae4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java
@@ -23,7 +23,10 @@
 
 import com.github.javaparser.JavaParser;
 import com.github.javaparser.Range;
-import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
 import com.github.javaparser.ast.comments.Comment;
 import com.github.javaparser.ast.comments.JavadocComment;
 import com.github.javaparser.ast.expr.Name;
@@ -70,6 +73,10 @@
         this(null, null, new NodeList<>(), new NodeList<>());
     }
 
+    public CompilationUnit(String packageDeclaration) {
+        this(null, new PackageDeclaration(new Name(packageDeclaration)), new NodeList<>(), new NodeList<>());
+    }
+
     public CompilationUnit(PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types) {
         this(null, packageDeclaration, imports, types);
     }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java
index c762681..d22b15d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java
@@ -59,6 +59,13 @@
                 new NodeList<>());
     }
 
+    public TypeParameter(final String name) {
+        this(null,
+                new SimpleName(name),
+                new NodeList<>(),
+                new NodeList<>());
+    }
+
     public TypeParameter(final String name, final NodeList<ClassOrInterfaceType> typeBound) {
         this(null,
                 new SimpleName(name),
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 61910f4..dac43ae 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
@@ -21,14 +21,9 @@
 
 package com.github.javaparser.ast.visitor;
 
-import com.github.javaparser.ast.ArrayCreationLevel;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.comments.BlockComment;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.comments.LineComment;
+import com.github.javaparser.ast.comments.*;
 import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.imports.*;
 import com.github.javaparser.ast.stmt.*;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/model/FieldModel.java b/javaparser-core/src/main/java/com/github/javaparser/model/FieldModel.java
new file mode 100644
index 0000000..35a7455
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/model/FieldModel.java
@@ -0,0 +1,42 @@
+package com.github.javaparser.model;
+
+import java.lang.reflect.Field;
+
+public class FieldModel {
+    private final NodeModel nodeModel;
+    private final Field field;
+
+    public FieldModel(NodeModel nodeModel, Field field) {
+        this.nodeModel = nodeModel;
+        this.field = field;
+    }
+    
+    void initialize() {
+        
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        FieldModel that = (FieldModel) o;
+
+        if (!field.equals(that.field)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return field.hashCode();
+    }
+
+    public NodeModel getNodeModel() {
+        return nodeModel;
+    }
+
+    public Field getField() {
+        return field;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/model/JavaParserModel.java b/javaparser-core/src/main/java/com/github/javaparser/model/JavaParserModel.java
new file mode 100644
index 0000000..fa4ff97
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/model/JavaParserModel.java
@@ -0,0 +1,154 @@
+package com.github.javaparser.model;
+
+import com.github.javaparser.ast.ArrayCreationLevel;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.comments.BlockComment;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.ast.comments.LineComment;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.imports.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * The model contains meta-data about all nodes in the AST.
+ * You can base source code generators on it.
+ */
+public class JavaParserModel {
+    private static Set<Class<? extends Node>> ALL_NODE_CLASSES = new HashSet<Class<? extends Node>>() {{
+        add(ArrayCreationLevel.class);
+        add(CompilationUnit.class);
+        add(Node.class);
+        add(PackageDeclaration.class);
+
+        add(AnnotationDeclaration.class);
+        add(AnnotationMemberDeclaration.class);
+        add(BodyDeclaration.class);
+        add(ClassOrInterfaceDeclaration.class);
+        add(ConstructorDeclaration.class);
+        add(EmptyMemberDeclaration.class);
+        add(EnumConstantDeclaration.class);
+        add(EnumDeclaration.class);
+        add(FieldDeclaration.class);
+        add(InitializerDeclaration.class);
+        add(MethodDeclaration.class);
+        add(Parameter.class);
+        add(TypeDeclaration.class);
+        add(VariableDeclarator.class);
+
+        add(BlockComment.class);
+        add(Comment.class);
+        add(JavadocComment.class);
+        add(LineComment.class);
+
+        add(AnnotationExpr.class);
+        add(ArrayAccessExpr.class);
+        add(ArrayCreationExpr.class);
+        add(ArrayInitializerExpr.class);
+        add(AssignExpr.class);
+        add(BinaryExpr.class);
+        add(BooleanLiteralExpr.class);
+        add(CastExpr.class);
+        add(CharLiteralExpr.class);
+        add(ClassExpr.class);
+        add(ConditionalExpr.class);
+        add(DoubleLiteralExpr.class);
+        add(EnclosedExpr.class);
+        add(Expression.class);
+        add(FieldAccessExpr.class);
+        add(InstanceOfExpr.class);
+        add(IntegerLiteralExpr.class);
+        add(LambdaExpr.class);
+        add(LiteralExpr.class);
+        add(LongLiteralExpr.class);
+        add(MarkerAnnotationExpr.class);
+        add(MemberValuePair.class);
+        add(MethodCallExpr.class);
+        add(MethodReferenceExpr.class);
+        add(NameExpr.class);
+        add(Name.class);
+        add(NormalAnnotationExpr.class);
+        add(NullLiteralExpr.class);
+        add(ObjectCreationExpr.class);
+        add(SimpleName.class);
+        add(SingleMemberAnnotationExpr.class);
+        add(StringLiteralExpr.class);
+        add(SuperExpr.class);
+        add(ThisExpr.class);
+        add(TypeExpr.class);
+        add(UnaryExpr.class);
+        add(VariableDeclarationExpr.class);
+
+        add(BadImportDeclaration.class);
+        add(ImportDeclaration.class);
+        add(SingleStaticImportDeclaration.class);
+        add(SingleTypeImportDeclaration.class);
+        add(StaticImportOnDemandDeclaration.class);
+        add(TypeImportOnDemandDeclaration.class);
+
+        add(AssertStmt.class);
+        add(BlockStmt.class);
+        add(BreakStmt.class);
+        add(CatchClause.class);
+        add(ContinueStmt.class);
+        add(DoStmt.class);
+        add(EmptyStmt.class);
+        add(ExplicitConstructorInvocationStmt.class);
+        add(ExpressionStmt.class);
+        add(ForeachStmt.class);
+        add(ForStmt.class);
+        add(IfStmt.class);
+        add(LabeledStmt.class);
+        add(ReturnStmt.class);
+        add(Statement.class);
+        add(SwitchEntryStmt.class);
+        add(SwitchStmt.class);
+        add(SynchronizedStmt.class);
+        add(ThrowStmt.class);
+        add(TryStmt.class);
+        add(TypeDeclarationStmt.class);
+        add(WhileStmt.class);
+
+        add(ArrayType.class);
+        add(ClassOrInterfaceType.class);
+        add(IntersectionType.class);
+        add(PrimitiveType.class);
+        add(ReferenceType.class);
+        add(Type.class);
+        add(TypeParameter.class);
+        add(UnionType.class);
+        add(UnknownType.class);
+        add(VoidType.class);
+        add(WildcardType.class);
+    }};
+
+    private final Set<NodeModel> nodeModels = new HashSet<>();
+
+    public JavaParserModel() {
+        for (Class<? extends Node> nodeClass : ALL_NODE_CLASSES) {
+            nodeModels.add(new NodeModel(this, nodeClass));
+        }
+        nodeModels.forEach(NodeModel::initialize);
+    }
+
+    public Set<NodeModel> getNodeModels() {
+        return nodeModels;
+    }
+
+    public Optional<NodeModel> getNodeModel(Class<?> c) {
+        for (NodeModel nodeModel : nodeModels) {
+            if (nodeModel.getNodeClass().equals(c)) {
+                return Optional.of(nodeModel);
+            }
+        }
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/model/NodeModel.java b/javaparser-core/src/main/java/com/github/javaparser/model/NodeModel.java
new file mode 100644
index 0000000..5b7e657
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/model/NodeModel.java
@@ -0,0 +1,72 @@
+package com.github.javaparser.model;
+
+import com.github.javaparser.ast.Node;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+public class NodeModel {
+    private final JavaParserModel javaParserModel;
+    private final Class<? extends Node> nodeClass;
+    private final Set<FieldModel> fieldModels = new HashSet<>();
+    private NodeModel superNodeModel;
+
+    public NodeModel(JavaParserModel javaParserModel, Class<? extends Node> nodeClass) {
+        this.javaParserModel = javaParserModel;
+        this.nodeClass = nodeClass;
+    }
+
+    void initialize() {
+        for (Field field : nodeClass.getDeclaredFields()) {
+            fieldModels.add(new FieldModel(this, field));
+        }
+
+        Class<?> superclass = nodeClass.getSuperclass();
+        if (Node.class.isAssignableFrom(superclass)) {
+            superNodeModel = javaParserModel.getNodeModel(superclass).get();
+        }
+
+        fieldModels.forEach(FieldModel::initialize);
+    }
+
+    public NodeModel getSuperNodeModel() {
+        return superNodeModel;
+    }
+
+    public JavaParserModel getJavaParserModel() {
+        return javaParserModel;
+    }
+
+    public Set<FieldModel> getFieldModels() {
+        return fieldModels;
+    }
+
+    public Class<? extends Node> getNodeClass() {
+        return nodeClass;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        NodeModel nodeModel = (NodeModel) o;
+
+        if (!nodeClass.equals(nodeModel.nodeClass)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return nodeClass.hashCode();
+    }
+
+    public String getClassName() {
+        return nodeClass.getSimpleName();
+    }
+    public String getQualifiedClassName() {
+        return nodeClass.getName();
+    }
+}
diff --git a/pom.xml b/pom.xml
index 65cfbd8..d288d59 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,6 +3,7 @@
     <modules>
         <module>javaparser-core</module>
         <module>javaparser-testing</module>
+        <module>javaparser-bootstrap</module>
     </modules>
 
     <groupId>com.github.javaparser</groupId>